hello world example working

This commit is contained in:
Evan Almloff committed 2024-01-05 18:01:05 -06:00
1 parent 3865f44081
commit 4013341b6c
22 files changed
+159 -176

No files matched your search

+1 -34
View File
@@ -147,9 +147,7 @@ pub mod utils;
pub use utils::DeserializerArgs;
pub use utils::DeserializerOutput;
pub use utils::TypeHelper;
use dioxus_core::{Element, Scope};
use syn::parse::{Parse, ParseStream};
use syn::spanned::Spanned;
use syn::*;
@@ -167,12 +165,6 @@ pub struct ComponentBody {
/// Keep this in mind when creating deserializers, because you often might want to ignore it.
/// That might be annoying, but it would be bad design for this kind of struct to not be parsable from itself.
pub item_fn: ItemFn,
/// Parsing tries to ensure that this argument will be a [`Scope`].
/// **However, macros have limitations that prevent this from always working,
/// so don't take this for granted!**
pub cx_arg: FnArg,
/// The pattern (name) and type of the context argument.
pub cx_pat_type: PatType,
/// If the function has any arguments other than the context.
pub has_extra_args: bool,
}
@@ -192,31 +184,8 @@ impl ComponentBody {
impl Parse for ComponentBody {
fn parse(input: ParseStream) -> Result<Self> {
let item_fn: ItemFn = input.parse()?;
let scope_type_path = Scope::get_path_string();
let (cx_arg, cx_pat_type) = if let Some(first_arg) = item_fn.sig.inputs.first() {
let incorrect_first_arg_err = Err(Error::new(
first_arg.span(),
format!("First argument must be a <{}>", scope_type_path),
));
match first_arg.to_owned() {
FnArg::Receiver(_) => {
return incorrect_first_arg_err;
}
FnArg::Typed(f) => (first_arg.to_owned(), f),
}
} else {
return Err(Error::new(
item_fn.sig.ident.span(), // Or maybe just item_f.sig.span()?
format!(
"Must have at least one argument that's a <{}>",
scope_type_path
),
));
};
let element_type_path = Element::get_path_string();
let element_type_path = "::dioxus::core::Element";
if item_fn.sig.output == ReturnType::Default {
return Err(Error::new(
@@ -229,8 +198,6 @@ impl Parse for ComponentBody {
Ok(Self {
item_fn,
cx_arg,
cx_pat_type,
has_extra_args,
})
}
@@ -1,5 +1,4 @@
use crate::component_body::ComponentBody;
use dioxus_core::{Element, Scope};
use quote::ToTokens;
use syn::{parse_quote, Path};
@@ -36,22 +35,3 @@ where
#[allow(unused_qualifications)]
fn to_output(&self, component_body: &ComponentBody) -> syn::Result<TOutput>;
}
pub trait TypeHelper {
fn get_path() -> Path;
fn get_path_string() -> String {
Self::get_path().to_token_stream().to_string()
}
}
impl<'a> TypeHelper for Scope<'a> {
fn get_path() -> Path {
parse_quote!(::dioxus::core::Scope)
}
}
impl<'a> TypeHelper for Element<'a> {
fn get_path() -> Path {
parse_quote!(::dioxus::core::Element)
}
}
@@ -16,7 +16,7 @@ To ignore this check, pass the \"",
const INNER_FN_NAME: &str = "__dx_inner_comp";
fn get_out_comp_fn(orig_comp_fn: &ItemFn, cx_pat: &Pat) -> ItemFn {
fn get_out_comp_fn(orig_comp_fn: &ItemFn) -> ItemFn {
let inner_comp_ident = Ident::new(INNER_FN_NAME, orig_comp_fn.sig.ident.span());
let inner_comp_fn = ItemFn {
@@ -34,7 +34,7 @@ fn get_out_comp_fn(orig_comp_fn: &ItemFn, cx_pat: &Pat) -> ItemFn {
#[allow(clippy::inline_always)]
#[inline(always)]
#inner_comp_fn
#inner_comp_ident (#cx_pat)
#inner_comp_ident(__props)
}
},
..orig_comp_fn.clone()
@@ -88,14 +88,9 @@ impl DeserializerArgs<ComponentDeserializerOutput> for ComponentDeserializerArgs
impl ComponentDeserializerArgs {
fn deserialize_no_props(component_body: &ComponentBody) -> ComponentDeserializerOutput {
let ComponentBody {
item_fn,
cx_pat_type,
..
} = component_body;
let cx_pat = &cx_pat_type.pat;
let ComponentBody { item_fn, .. } = component_body;
let comp_fn = get_out_comp_fn(item_fn, cx_pat);
let comp_fn = get_out_comp_fn(item_fn);
ComponentDeserializerOutput {
comp_fn,
@@ -106,12 +101,7 @@ impl ComponentDeserializerArgs {
fn deserialize_with_props(
component_body: &ComponentBody,
) -> Result<ComponentDeserializerOutput> {
let ComponentBody {
item_fn,
cx_pat_type,
..
} = component_body;
let cx_pat = &cx_pat_type.pat;
let ComponentBody { item_fn, .. } = component_body;
let comp_parsed = match parse2::<ComponentBody>(quote!(#item_fn)) {
Ok(comp_body) => comp_body,
@@ -130,7 +120,7 @@ impl ComponentDeserializerArgs {
let props_struct = inlined_props_output.props_struct;
let props_fn = inlined_props_output.comp_fn;
let comp_fn = get_out_comp_fn(&props_fn, cx_pat);
let comp_fn = get_out_comp_fn(&props_fn);
Ok(ComponentDeserializerOutput {
comp_fn,
@@ -225,11 +225,7 @@ fn get_props_docs(fn_ident: &Ident, inputs: Vec<&FnArg>) -> Vec<Attribute> {
}
fn get_function(component_body: &ComponentBody) -> ItemFn {
let ComponentBody {
item_fn,
cx_pat_type,
..
} = component_body;
let ComponentBody { item_fn, .. } = component_body;
let ItemFn {
attrs: fn_attrs,
vis,
@@ -246,7 +242,6 @@ fn get_function(component_body: &ComponentBody) -> ItemFn {
} = sig;
let Generics { where_clause, .. } = generics;
let cx_pat = &cx_pat_type.pat;
let struct_ident = Ident::new(&format!("{fn_ident}Props"), fn_ident.span());
// Skip first arg since that's the context
@@ -298,10 +293,10 @@ fn get_function(component_body: &ComponentBody) -> ItemFn {
parse_quote! {
#(#fn_attrs)*
#(#props_docs)*
#asyncness #vis fn #fn_ident #fn_generics (#cx_pat: Scope<#scope_lifetime #struct_ident #generics_no_bounds>) #fn_output
#asyncness #vis fn #fn_ident #fn_generics (__props: #struct_ident #generics_no_bounds) #fn_output
#where_clause
{
let #struct_ident { #(#struct_field_names),* } = &#cx_pat.props;
let #struct_ident { #(#struct_field_names),* } = &__props;
#fn_block
}
}