summaryrefslogtreecommitdiff
path: root/macros/src/node.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-12-15 22:51:55 +0100
committerLaurenz <laurmaedje@gmail.com>2022-12-15 23:11:20 +0100
commitb6202b646a0d5ecced301d9bac8bfcaf977d7ee4 (patch)
tree7d42cb50f9e66153e7e8b2217009684e25f54f42 /macros/src/node.rs
parentf3980c704544a464f9729cc8bc9f97d3a7454769 (diff)
Reflection for castables
Diffstat (limited to 'macros/src/node.rs')
-rw-r--r--macros/src/node.rs46
1 files changed, 41 insertions, 5 deletions
diff --git a/macros/src/node.rs b/macros/src/node.rs
index 192ca667..ad079c0e 100644
--- a/macros/src/node.rs
+++ b/macros/src/node.rs
@@ -36,6 +36,7 @@ struct Property {
shorthand: Option<Shorthand>,
resolve: bool,
fold: bool,
+ reflect: bool,
}
/// The shorthand form of a style property.
@@ -117,6 +118,7 @@ fn prepare_property(item: &syn::ImplItemConst) -> Result<Property> {
let mut referenced = false;
let mut resolve = false;
let mut fold = false;
+ let mut reflect = false;
// Parse the `#[property(..)]` attribute.
let mut stream = tokens.into_iter().peekable();
@@ -150,14 +152,11 @@ fn prepare_property(item: &syn::ImplItemConst) -> Result<Property> {
"referenced" => referenced = true,
"resolve" => resolve = true,
"fold" => fold = true,
+ "reflect" => reflect = true,
_ => bail!(ident, "invalid attribute"),
}
}
- if skip && shorthand.is_some() {
- bail!(item.ident, "skip and shorthand are mutually exclusive");
- }
-
if referenced && (fold || resolve) {
bail!(item.ident, "referenced is mutually exclusive with fold and resolve");
}
@@ -193,6 +192,7 @@ fn prepare_property(item: &syn::ImplItemConst) -> Result<Property> {
referenced,
resolve,
fold,
+ reflect,
})
}
@@ -205,6 +205,7 @@ fn create(node: &Node) -> Result<TokenStream> {
let name_method = create_node_name_method(node);
let construct_func = create_node_construct_func(node);
let set_func = create_node_set_func(node);
+ let properties_func = create_node_properties_func(node);
let field_method = create_node_field_method(node);
let node_impl = quote! {
@@ -213,6 +214,7 @@ fn create(node: &Node) -> Result<TokenStream> {
#name_method
#construct_func
#set_func
+ #properties_func
#field_method
}
};
@@ -221,7 +223,7 @@ fn create(node: &Node) -> Result<TokenStream> {
let mut items: Vec<syn::ImplItem> = vec![];
let scope = quote::format_ident!("__{}_keys", node.self_name);
- for property in &node.properties {
+ for property in node.properties.iter() {
let (key, module) = create_property_module(node, &property);
modules.push(module);
@@ -331,6 +333,40 @@ fn create_node_set_func(node: &Node) -> syn::ImplItemMethod {
}
}
+/// Create the node's `properties` function.
+fn create_node_properties_func(node: &Node) -> syn::ImplItemMethod {
+ let infos = node
+ .properties
+ .iter()
+ .filter(|p| !p.skip || p.reflect)
+ .map(|property| {
+ let name = property.name.to_string().replace('_', "-").to_lowercase();
+ let docs = doc_comment(&property.attrs);
+ let value_ty = &property.value_ty;
+ let shorthand = matches!(property.shorthand, Some(Shorthand::Positional));
+ quote! {
+ ::typst::model::ParamInfo {
+ name: #name,
+ docs: #docs,
+ settable: true,
+ shorthand: #shorthand,
+ cast: <#value_ty as ::typst::model::Cast<
+ ::typst::syntax::Spanned<::typst::model::Value>
+ >>::describe(),
+ }
+ }
+ });
+
+ parse_quote! {
+ fn properties() -> ::std::vec::Vec<::typst::model::ParamInfo>
+ where
+ Self: Sized
+ {
+ ::std::vec![#(#infos),*]
+ }
+ }
+}
+
/// Create the node's `field` method.
fn create_node_field_method(node: &Node) -> syn::ImplItemMethod {
node.field.clone().unwrap_or_else(|| {