events: Allow to declare events without a stable prefix
This commit is contained in:
parent
c0b8cd4d46
commit
e780633cce
@ -4,7 +4,7 @@ use std::fmt;
|
|||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::{format_ident, quote, IdentFragment, ToTokens};
|
use quote::{format_ident, quote, IdentFragment, ToTokens};
|
||||||
use syn::{Attribute, Data, DataEnum, DeriveInput, Ident, LitStr, Path};
|
use syn::{Attribute, Data, DataEnum, DeriveInput, Ident, LitStr};
|
||||||
|
|
||||||
use super::event_parse::{EventEnumDecl, EventEnumEntry, EventKind};
|
use super::event_parse::{EventEnumDecl, EventEnumEntry, EventKind};
|
||||||
use crate::util::m_prefix_name_to_type_name;
|
use crate::util::m_prefix_name_to_type_name;
|
||||||
@ -114,14 +114,7 @@ fn expand_event_enum(
|
|||||||
let ident = kind.to_event_enum_ident(var.into())?;
|
let ident = kind.to_event_enum_ident(var.into())?;
|
||||||
|
|
||||||
let variant_decls = variants.iter().map(|v| v.decl());
|
let variant_decls = variants.iter().map(|v| v.decl());
|
||||||
let event_ty: Vec<_> = events
|
let event_ty: Vec<_> = events.iter().map(|event| event.to_event_path(kind, var)).collect();
|
||||||
.iter()
|
|
||||||
.map(|event| {
|
|
||||||
event
|
|
||||||
.stable_name()
|
|
||||||
.map(|stable_name| to_event_path(stable_name, &event.ev_path, kind, var))
|
|
||||||
})
|
|
||||||
.collect::<syn::Result<_>>()?;
|
|
||||||
|
|
||||||
let custom_content_ty = format_ident!("Custom{}Content", kind);
|
let custom_content_ty = format_ident!("Custom{}Content", kind);
|
||||||
|
|
||||||
@ -175,7 +168,7 @@ fn expand_deserialize_impl(
|
|||||||
quote! { #(#attrs)* }
|
quote! { #(#attrs)* }
|
||||||
};
|
};
|
||||||
let self_variant = variant.ctor(quote! { Self });
|
let self_variant = variant.ctor(quote! { Self });
|
||||||
let content = to_event_path(event.stable_name()?, &event.ev_path, kind, var);
|
let content = event.to_event_path(kind, var);
|
||||||
let ev_types = event.aliases.iter().chain([&event.ev_type]);
|
let ev_types = event.aliases.iter().chain([&event.ev_type]);
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
@ -314,13 +307,8 @@ fn expand_content_enum(
|
|||||||
|
|
||||||
let event_type_enum = kind.to_event_type_enum();
|
let event_type_enum = kind.to_event_type_enum();
|
||||||
|
|
||||||
let content: Vec<_> = events
|
let content: Vec<_> =
|
||||||
.iter()
|
events.iter().map(|event| event.to_event_content_path(kind, None)).collect();
|
||||||
.map(|event| {
|
|
||||||
let stable_name = event.stable_name()?;
|
|
||||||
Ok(to_event_content_path(kind, stable_name, &event.ev_path, None))
|
|
||||||
})
|
|
||||||
.collect::<syn::Result<_>>()?;
|
|
||||||
|
|
||||||
let variant_decls = variants.iter().map(|v| v.decl()).collect::<Vec<_>>();
|
let variant_decls = variants.iter().map(|v| v.decl()).collect::<Vec<_>>();
|
||||||
let variant_arms = variants.iter().map(|v| v.match_arm(quote! { Self })).collect::<Vec<_>>();
|
let variant_arms = variants.iter().map(|v| v.match_arm(quote! { Self })).collect::<Vec<_>>();
|
||||||
@ -389,13 +377,8 @@ fn expand_full_content_enum(
|
|||||||
|
|
||||||
let event_type_enum = kind.to_event_type_enum();
|
let event_type_enum = kind.to_event_type_enum();
|
||||||
|
|
||||||
let content: Vec<_> = events
|
let content: Vec<_> =
|
||||||
.iter()
|
events.iter().map(|event| event.to_event_content_path(kind, None)).collect();
|
||||||
.map(|event| {
|
|
||||||
let stable_name = event.stable_name()?;
|
|
||||||
Ok(to_event_content_path(kind, stable_name, &event.ev_path, None))
|
|
||||||
})
|
|
||||||
.collect::<syn::Result<_>>()?;
|
|
||||||
|
|
||||||
let variant_decls = variants.iter().map(|v| v.decl()).collect::<Vec<_>>();
|
let variant_decls = variants.iter().map(|v| v.decl()).collect::<Vec<_>>();
|
||||||
let variant_arms = variants.iter().map(|v| v.match_arm(quote! { Self })).collect::<Vec<_>>();
|
let variant_arms = variants.iter().map(|v| v.match_arm(quote! { Self })).collect::<Vec<_>>();
|
||||||
@ -669,41 +652,6 @@ fn expand_accessor_methods(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_event_path(
|
|
||||||
name: &LitStr,
|
|
||||||
path: &Path,
|
|
||||||
kind: EventKind,
|
|
||||||
var: EventEnumVariation,
|
|
||||||
) -> TokenStream {
|
|
||||||
let event = m_prefix_name_to_type_name(name).unwrap();
|
|
||||||
let event_name = if kind == EventKind::ToDevice {
|
|
||||||
assert_eq!(var, EventEnumVariation::None);
|
|
||||||
format_ident!("ToDevice{}Event", event)
|
|
||||||
} else {
|
|
||||||
format_ident!("{}{}Event", var, event)
|
|
||||||
};
|
|
||||||
quote! { #path::#event_name }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_event_content_path(
|
|
||||||
kind: EventKind,
|
|
||||||
name: &LitStr,
|
|
||||||
path: &Path,
|
|
||||||
prefix: Option<&str>,
|
|
||||||
) -> TokenStream {
|
|
||||||
let event = m_prefix_name_to_type_name(name).unwrap();
|
|
||||||
let content_str = match kind {
|
|
||||||
EventKind::ToDevice => {
|
|
||||||
format_ident!("ToDevice{}{}EventContent", prefix.unwrap_or(""), event)
|
|
||||||
}
|
|
||||||
_ => format_ident!("{}{}EventContent", prefix.unwrap_or(""), event),
|
|
||||||
};
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#path::#content_str
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field_return_type(name: &str, ruma_common: &TokenStream) -> TokenStream {
|
fn field_return_type(name: &str, ruma_common: &TokenStream) -> TokenStream {
|
||||||
match name {
|
match name {
|
||||||
"origin_server_ts" => quote! { #ruma_common::MilliSecondsSinceUnixEpoch },
|
"origin_server_ts" => quote! { #ruma_common::MilliSecondsSinceUnixEpoch },
|
||||||
@ -758,7 +706,7 @@ impl EventEnumEntry {
|
|||||||
|
|
||||||
pub(crate) fn to_variant(&self) -> syn::Result<EventEnumVariant> {
|
pub(crate) fn to_variant(&self) -> syn::Result<EventEnumVariant> {
|
||||||
let attrs = self.attrs.clone();
|
let attrs = self.attrs.clone();
|
||||||
let ident = m_prefix_name_to_type_name(self.stable_name()?)?;
|
let ident = self.ident()?;
|
||||||
|
|
||||||
Ok(EventEnumVariant { attrs, ident })
|
Ok(EventEnumVariant { attrs, ident })
|
||||||
}
|
}
|
||||||
@ -772,7 +720,8 @@ impl EventEnumEntry {
|
|||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
format!(
|
format!(
|
||||||
"A matrix event must declare a well-known type that starts with `m.` \
|
"A matrix event must declare a well-known type that starts with `m.` \
|
||||||
either as the main type or as an alias, found `{}`",
|
either as the main type or as an alias, or must declare the ident that \
|
||||||
|
should be used if it is only an unstable type, found main type `{}`",
|
||||||
self.ev_type.value()
|
self.ev_type.value()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -780,14 +729,49 @@ impl EventEnumEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn docs(&self) -> syn::Result<TokenStream> {
|
pub(crate) fn ident(&self) -> syn::Result<Ident> {
|
||||||
let stable_name = self.stable_name()?;
|
if let Some(ident) = self.ident.clone() {
|
||||||
|
Ok(ident)
|
||||||
|
} else {
|
||||||
|
m_prefix_name_to_type_name(self.stable_name()?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut doc = quote! {
|
fn to_event_path(&self, kind: EventKind, var: EventEnumVariation) -> TokenStream {
|
||||||
#[doc = #stable_name]
|
let path = &self.ev_path;
|
||||||
|
let ident = self.ident().unwrap();
|
||||||
|
let event_name = if kind == EventKind::ToDevice {
|
||||||
|
assert_eq!(var, EventEnumVariation::None);
|
||||||
|
format_ident!("ToDevice{ident}Event")
|
||||||
|
} else {
|
||||||
|
format_ident!("{}{ident}Event", var)
|
||||||
|
};
|
||||||
|
quote! { #path::#event_name }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_event_content_path(&self, kind: EventKind, prefix: Option<&str>) -> TokenStream {
|
||||||
|
let path = &self.ev_path;
|
||||||
|
let ident = self.ident().unwrap();
|
||||||
|
let content_str = match kind {
|
||||||
|
EventKind::ToDevice => {
|
||||||
|
format_ident!("ToDevice{}{ident}EventContent", prefix.unwrap_or(""))
|
||||||
|
}
|
||||||
|
_ => format_ident!("{}{ident}EventContent", prefix.unwrap_or("")),
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.ev_type != *stable_name {
|
quote! {
|
||||||
|
#path::#content_str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn docs(&self) -> syn::Result<TokenStream> {
|
||||||
|
let main_name = self.stable_name().unwrap_or(&self.ev_type);
|
||||||
|
|
||||||
|
let mut doc = quote! {
|
||||||
|
#[doc = #main_name]
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.ev_type != *main_name {
|
||||||
let unstable_name =
|
let unstable_name =
|
||||||
format!("This variant uses the unstable type `{}`.", self.ev_type.value());
|
format!("This variant uses the unstable type `{}`.", self.ev_type.value());
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ mod kw {
|
|||||||
syn::custom_keyword!(kind);
|
syn::custom_keyword!(kind);
|
||||||
syn::custom_keyword!(events);
|
syn::custom_keyword!(events);
|
||||||
syn::custom_keyword!(alias);
|
syn::custom_keyword!(alias);
|
||||||
|
syn::custom_keyword!(ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the variants of this enum change `to_event_path` needs to be updated as well.
|
// If the variants of this enum change `to_event_path` needs to be updated as well.
|
||||||
@ -228,6 +229,7 @@ pub struct EventEnumEntry {
|
|||||||
pub aliases: Vec<LitStr>,
|
pub aliases: Vec<LitStr>,
|
||||||
pub ev_type: LitStr,
|
pub ev_type: LitStr,
|
||||||
pub ev_path: Path,
|
pub ev_path: Path,
|
||||||
|
pub ident: Option<Ident>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for EventEnumEntry {
|
impl Parse for EventEnumEntry {
|
||||||
@ -242,24 +244,38 @@ impl Parse for EventEnumEntry {
|
|||||||
let has_suffix = ev_type.value().ends_with(".*");
|
let has_suffix = ev_type.value().ends_with(".*");
|
||||||
|
|
||||||
let mut aliases = Vec::with_capacity(ruma_enum_attrs.len());
|
let mut aliases = Vec::with_capacity(ruma_enum_attrs.len());
|
||||||
for attr_list in ruma_enum_attrs {
|
let mut ident = None;
|
||||||
for alias_attr in attr_list
|
|
||||||
.parse_args_with(Punctuated::<EventEnumAliasAttr, Token![,]>::parse_terminated)?
|
|
||||||
{
|
|
||||||
let alias = alias_attr.into_inner();
|
|
||||||
|
|
||||||
if alias.value().ends_with(".*") == has_suffix {
|
for attr_list in ruma_enum_attrs {
|
||||||
aliases.push(alias);
|
for attr in attr_list
|
||||||
} else {
|
.parse_args_with(Punctuated::<EventEnumAttr, Token![,]>::parse_terminated)?
|
||||||
return Err(syn::Error::new_spanned(
|
{
|
||||||
&attr_list,
|
match attr {
|
||||||
"aliases should have the same `.*` suffix, or lack thereof, as the main event type",
|
EventEnumAttr::Alias(alias) => {
|
||||||
));
|
if alias.value().ends_with(".*") == has_suffix {
|
||||||
|
aliases.push(alias);
|
||||||
|
} else {
|
||||||
|
return Err(syn::Error::new_spanned(
|
||||||
|
&attr_list,
|
||||||
|
"aliases should have the same `.*` suffix, or lack thereof, as the main event type",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EventEnumAttr::Ident(i) => {
|
||||||
|
if ident.is_some() {
|
||||||
|
return Err(syn::Error::new_spanned(
|
||||||
|
&attr_list,
|
||||||
|
"multiple `ident` attributes found, there can be only one",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ident = Some(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self { attrs, aliases, ev_type, ev_path })
|
Ok(Self { attrs, aliases, ev_type, ev_path, ident })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,19 +320,27 @@ impl Parse for EventEnumInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventEnumAliasAttr(LitStr);
|
pub enum EventEnumAttr {
|
||||||
|
Alias(LitStr),
|
||||||
impl EventEnumAliasAttr {
|
Ident(Ident),
|
||||||
pub fn into_inner(self) -> LitStr {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for EventEnumAliasAttr {
|
impl Parse for EventEnumAttr {
|
||||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||||
let _: kw::alias = input.parse()?;
|
let lookahead = input.lookahead1();
|
||||||
let _: Token![=] = input.parse()?;
|
|
||||||
let s: LitStr = input.parse()?;
|
if lookahead.peek(kw::alias) {
|
||||||
Ok(Self(s))
|
let _: kw::alias = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
let s: LitStr = input.parse()?;
|
||||||
|
Ok(Self::Alias(s))
|
||||||
|
} else if lookahead.peek(kw::ident) {
|
||||||
|
let _: kw::ident = input.parse()?;
|
||||||
|
let _: Token![=] = input.parse()?;
|
||||||
|
let i: Ident = input.parse()?;
|
||||||
|
Ok(Self::Ident(i))
|
||||||
|
} else {
|
||||||
|
Err(lookahead.error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ pub fn expand_event_type_enum(
|
|||||||
aliases: vec![],
|
aliases: vec![],
|
||||||
ev_type: LitStr::new("m.presence", Span::call_site()),
|
ev_type: LitStr::new("m.presence", Span::call_site()),
|
||||||
ev_path: parse_quote! { #ruma_common::events::presence },
|
ev_path: parse_quote! { #ruma_common::events::presence },
|
||||||
|
ident: None,
|
||||||
}];
|
}];
|
||||||
let mut all = input.enums.iter().map(|e| &e.events).collect::<Vec<_>>();
|
let mut all = input.enums.iter().map(|e| &e.events).collect::<Vec<_>>();
|
||||||
all.push(&presence);
|
all.push(&presence);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user