summaryrefslogtreecommitdiff
path: root/crates/typst-macros/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-01-12 14:36:41 +0100
committerLaurenz <laurmaedje@gmail.com>2024-01-12 14:43:42 +0100
commit37249c20f793689b523cbb379f30b37466ca51b9 (patch)
treee1af42115de7685c43eee109d7f86ef0e69979e6 /crates/typst-macros/src
parent1834ebc52918754dee51afffd8b55e82613eb687 (diff)
Autogenerate default cast in`#[ty]` unless `cast` is specified
Diffstat (limited to 'crates/typst-macros/src')
-rw-r--r--crates/typst-macros/src/lib.rs2
-rw-r--r--crates/typst-macros/src/ty.rs34
-rw-r--r--crates/typst-macros/src/util.rs1
3 files changed, 20 insertions, 17 deletions
diff --git a/crates/typst-macros/src/lib.rs b/crates/typst-macros/src/lib.rs
index 8ca7bcac..a9185a9b 100644
--- a/crates/typst-macros/src/lib.rs
+++ b/crates/typst-macros/src/lib.rs
@@ -116,6 +116,8 @@ pub fn func(stream: BoundaryStream, item: BoundaryStream) -> BoundaryStream {
/// You can customize some properties of the resulting type:
/// - `scope`: Indicates that the type has an associated scope defined by the
/// `#[scope]` macro
+/// - `cast`: Indicates that the type has a custom `cast!` implementation.
+/// The macro will then not autogenerate one.
/// - `name`: The type's normal name (e.g. `str`). Defaults to the Rust name in
/// kebab-case.
/// - `title`: The type's title case name (e.g. `String`). Defaults to the
diff --git a/crates/typst-macros/src/ty.rs b/crates/typst-macros/src/ty.rs
index 23f818bd..943bd453 100644
--- a/crates/typst-macros/src/ty.rs
+++ b/crates/typst-macros/src/ty.rs
@@ -28,18 +28,18 @@ pub fn ty(stream: TokenStream, item: syn::Item) -> Result<TokenStream> {
/// Holds all relevant parsed data about a type.
struct Type {
+ meta: Meta,
ident: Ident,
name: String,
long: String,
- scope: bool,
title: String,
docs: String,
- keywords: Vec<String>,
}
/// The `..` in `#[ty(..)]`.
struct Meta {
scope: bool,
+ cast: bool,
name: Option<String>,
title: Option<String>,
keywords: Vec<String>,
@@ -49,6 +49,7 @@ impl Parse for Meta {
fn parse(input: ParseStream) -> Result<Self> {
Ok(Self {
scope: parse_flag::<kw::scope>(input)?,
+ cast: parse_flag::<kw::cast>(input)?,
name: parse_string::<kw::name>(input)?,
title: parse_string::<kw::title>(input)?,
keywords: parse_string_array::<kw::keywords>(input)?,
@@ -59,37 +60,35 @@ impl Parse for Meta {
/// Parse details about the type from its definition.
fn parse(meta: Meta, ident: Ident, attrs: &[Attribute]) -> Result<Type> {
let docs = documentation(attrs);
- let (name, title) = determine_name_and_title(meta.name, meta.title, &ident, None)?;
+ let (name, title) =
+ determine_name_and_title(meta.name.clone(), meta.title.clone(), &ident, None)?;
let long = title.to_lowercase();
- Ok(Type {
- ident,
- name,
- long,
- scope: meta.scope,
- keywords: meta.keywords,
- title,
- docs,
- })
+ Ok(Type { meta, ident, name, long, title, docs })
}
/// Produce the output of the macro.
fn create(ty: &Type, item: Option<&syn::Item>) -> TokenStream {
- let Type {
- ident, name, long, title, docs, keywords, scope, ..
- } = ty;
+ let Type { ident, name, long, title, docs, meta, .. } = ty;
+ let Meta { keywords, .. } = meta;
- let constructor = if *scope {
+ let constructor = if meta.scope {
quote! { <#ident as #foundations::NativeScope>::constructor() }
} else {
quote! { None }
};
- let scope = if *scope {
+ let scope = if meta.scope {
quote! { <#ident as #foundations::NativeScope>::scope() }
} else {
quote! { #foundations::Scope::new() }
};
+ let cast = (!meta.cast).then(|| {
+ quote! {
+ #foundations::cast! { type #ident, }
+ }
+ });
+
let data = quote! {
#foundations::NativeTypeData {
name: #name,
@@ -104,6 +103,7 @@ fn create(ty: &Type, item: Option<&syn::Item>) -> TokenStream {
quote! {
#item
+ #cast
impl #foundations::NativeType for #ident {
const NAME: &'static str = #name;
diff --git a/crates/typst-macros/src/util.rs b/crates/typst-macros/src/util.rs
index 4f7cc5fb..89880db1 100644
--- a/crates/typst-macros/src/util.rs
+++ b/crates/typst-macros/src/util.rs
@@ -255,6 +255,7 @@ pub mod kw {
syn::custom_keyword!(span);
syn::custom_keyword!(title);
syn::custom_keyword!(scope);
+ syn::custom_keyword!(cast);
syn::custom_keyword!(constructor);
syn::custom_keyword!(keywords);
syn::custom_keyword!(parent);