diff --git a/crates/ruma-common/src/events/enums.rs b/crates/ruma-common/src/events/enums.rs index a427f545..3d97ede9 100644 --- a/crates/ruma-common/src/events/enums.rs +++ b/crates/ruma-common/src/events/enums.rs @@ -15,108 +15,108 @@ use crate::{ event_enum! { /// Any global account data event. enum GlobalAccountData { - "m.direct", - "m.identity_server", - "m.ignored_user_list", - "m.push_rules", - "m.secret_storage.default_key", - "m.secret_storage.key.*", + "m.direct" => super::direct, + "m.identity_server" => super::identity_server, + "m.ignored_user_list" => super::ignored_user_list, + "m.push_rules" => super::push_rules, + "m.secret_storage.default_key" => super::secret_storage::default_key, + "m.secret_storage.key.*" => super::secret_storage::key, } /// Any room account data event. enum RoomAccountData { - "m.fully_read", - "m.tag", + "m.fully_read" => super::fully_read, + "m.tag" => super::tag, } /// Any ephemeral room event. enum EphemeralRoom { - "m.receipt", - "m.typing", + "m.receipt" => super::receipt, + "m.typing" => super::typing, } /// Any message-like event. enum MessageLike { #[cfg(feature = "unstable-msc3246")] - "m.audio", - "m.call.answer", - "m.call.invite", - "m.call.hangup", - "m.call.candidates", + "m.audio" => super::audio, + "m.call.answer" => super::call::answer, + "m.call.invite" => super::call::invite, + "m.call.hangup" => super::call::hangup, + "m.call.candidates" => super::call::candidates, #[cfg(feature = "unstable-msc1767")] - "m.emote", + "m.emote" => super::emote, #[cfg(feature = "unstable-msc3551")] - "m.file", + "m.file" => super::file, #[cfg(feature = "unstable-msc3552")] - "m.image", - "m.key.verification.ready", - "m.key.verification.start", - "m.key.verification.cancel", - "m.key.verification.accept", - "m.key.verification.key", - "m.key.verification.mac", - "m.key.verification.done", + "m.image" => super::image, + "m.key.verification.ready" => super::key::verification::ready, + "m.key.verification.start" => super::key::verification::start, + "m.key.verification.cancel" => super::key::verification::cancel, + "m.key.verification.accept" => super::key::verification::accept, + "m.key.verification.key" => super::key::verification::key, + "m.key.verification.mac" => super::key::verification::mac, + "m.key.verification.done" => super::key::verification::done, #[cfg(feature = "unstable-msc3488")] - "m.location", + "m.location" => super::location, #[cfg(feature = "unstable-msc1767")] - "m.message", + "m.message" => super::message, #[cfg(feature = "unstable-msc1767")] - "m.notice", + "m.notice" => super::notice, #[cfg(feature = "unstable-msc2677")] - "m.reaction", - "m.room.encrypted", - "m.room.message", - "m.room.message.feedback", - "m.room.redaction", - "m.sticker", + "m.reaction" => super::reaction, + "m.room.encrypted" => super::room::encrypted, + "m.room.message" => super::room::message, + "m.room.message.feedback" => super::room::message::feedback, + "m.room.redaction" => super::room::redaction, + "m.sticker" => super::sticker, #[cfg(feature = "unstable-msc3553")] - "m.video", + "m.video" => super::video, #[cfg(feature = "unstable-msc3245")] - "m.voice", + "m.voice" => super::voice, } /// Any state event. enum State { - "m.policy.rule.room", - "m.policy.rule.server", - "m.policy.rule.user", - "m.room.aliases", - "m.room.avatar", - "m.room.canonical_alias", - "m.room.create", - "m.room.encryption", - "m.room.guest_access", - "m.room.history_visibility", - "m.room.join_rules", - "m.room.member", - "m.room.name", - "m.room.pinned_events", - "m.room.power_levels", - "m.room.server_acl", - "m.room.third_party_invite", - "m.room.tombstone", - "m.room.topic", - "m.space.child", - "m.space.parent", + "m.policy.rule.room" => super::policy::rule::room, + "m.policy.rule.server" => super::policy::rule::server, + "m.policy.rule.user" => super::policy::rule::user, + "m.room.aliases" => super::room::aliases, + "m.room.avatar" => super::room::avatar, + "m.room.canonical_alias" => super::room::canonical_alias, + "m.room.create" => super::room::create, + "m.room.encryption" => super::room::encryption, + "m.room.guest_access" => super::room::guest_access, + "m.room.history_visibility" => super::room::history_visibility, + "m.room.join_rules" => super::room::join_rules, + "m.room.member" => super::room::member, + "m.room.name" => super::room::name, + "m.room.pinned_events" => super::room::pinned_events, + "m.room.power_levels" => super::room::power_levels, + "m.room.server_acl" => super::room::server_acl, + "m.room.third_party_invite" => super::room::third_party_invite, + "m.room.tombstone" => super::room::tombstone, + "m.room.topic" => super::room::topic, + "m.space.child" => super::space::child, + "m.space.parent" => super::space::parent, } /// Any to-device event. enum ToDevice { - "m.dummy", - "m.room_key", - "m.room_key_request", - "m.forwarded_room_key", - "m.key.verification.request", - "m.key.verification.ready", - "m.key.verification.start", - "m.key.verification.cancel", - "m.key.verification.accept", - "m.key.verification.key", - "m.key.verification.mac", - "m.key.verification.done", - "m.room.encrypted", - "m.secret.request", - "m.secret.send", + "m.dummy" => super::dummy, + "m.room_key" => super::room_key, + "m.room_key_request" => super::room_key_request, + "m.forwarded_room_key" => super::forwarded_room_key, + "m.key.verification.request" => super::key::verification::request, + "m.key.verification.ready" => super::key::verification::ready, + "m.key.verification.start" => super::key::verification::start, + "m.key.verification.cancel" => super::key::verification::cancel, + "m.key.verification.accept" => super::key::verification::accept, + "m.key.verification.key" => super::key::verification::key, + "m.key.verification.mac" => super::key::verification::mac, + "m.key.verification.done" => super::key::verification::done, + "m.room.encrypted" => super::room::encrypted, + "m.secret.request"=> super::secret::request, + "m.secret.send" => super::secret::send, } } diff --git a/crates/ruma-common/tests/events/ui/07-enum-sanity-check.rs b/crates/ruma-common/tests/events/ui/07-enum-sanity-check.rs index 78891007..ef939cac 100644 --- a/crates/ruma-common/tests/events/ui/07-enum-sanity-check.rs +++ b/crates/ruma-common/tests/events/ui/07-enum-sanity-check.rs @@ -1,15 +1,16 @@ +use ruma_common::events; use ruma_macros::event_enum; event_enum! { /// Any global account data event. enum GlobalAccountData { - "m.direct", + "m.direct" => events::direct, #[cfg(test)] - "m.ignored_user_list", + "m.ignored_user_list" => events::ignored_user_list, // Doesn't actually have a wildcard, but this should work as a wildcard test - "m.push_rules.*", + "m.push_rules.*" => events::push_rules, #[cfg(any())] - "m.ruma_test", + "m.ruma_test" => events::ruma_test, } } diff --git a/crates/ruma-common/tests/events/ui/08-enum-invalid-path.rs b/crates/ruma-common/tests/events/ui/08-enum-invalid-path.rs index e1362737..209cbcc1 100644 --- a/crates/ruma-common/tests/events/ui/08-enum-invalid-path.rs +++ b/crates/ruma-common/tests/events/ui/08-enum-invalid-path.rs @@ -1,8 +1,9 @@ +use ruma_common::events; use ruma_macros::event_enum; event_enum! { enum State { - "m.not.a.path", + "m.not.a.path" => events::not::a::path, } } diff --git a/crates/ruma-common/tests/events/ui/08-enum-invalid-path.stderr b/crates/ruma-common/tests/events/ui/08-enum-invalid-path.stderr index 717b0e4b..bc28b542 100644 --- a/crates/ruma-common/tests/events/ui/08-enum-invalid-path.stderr +++ b/crates/ruma-common/tests/events/ui/08-enum-invalid-path.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: could not find `not` in `events` - --> tests/events/ui/08-enum-invalid-path.rs:5:9 + --> tests/events/ui/08-enum-invalid-path.rs:6:35 | -5 | "m.not.a.path", - | ^^^^^^^^^^^^^^ could not find `not` in `events` +6 | "m.not.a.path" => events::not::a::path, + | ^^^ could not find `not` in `events` diff --git a/crates/ruma-macros/src/events/event_enum.rs b/crates/ruma-macros/src/events/event_enum.rs index b091d303..65dcb15e 100644 --- a/crates/ruma-macros/src/events/event_enum.rs +++ b/crates/ruma-macros/src/events/event_enum.rs @@ -4,7 +4,7 @@ use std::fmt; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote, IdentFragment, ToTokens}; -use syn::{Attribute, Data, DataEnum, DeriveInput, Ident, LitStr}; +use syn::{Attribute, Data, DataEnum, DeriveInput, Ident, LitStr, Path}; use super::event_parse::{EventEnumDecl, EventEnumEntry, EventKind}; use crate::util::m_prefix_name_to_type_name; @@ -49,7 +49,8 @@ pub fn expand_event_enums(input: &EventEnumDecl) -> syn::Result { let kind = input.kind; let attrs = &input.attrs; - let events: Vec<_> = input.events.iter().map(|entry| entry.ev_type.clone()).collect(); + let events: Vec<_> = + input.events.iter().map(|entry| (entry.ev_type.clone(), entry.ev_path.clone())).collect(); let variants: Vec<_> = input.events.iter().map(EventEnumEntry::to_variant).collect::>()?; @@ -110,7 +111,7 @@ pub fn expand_event_enums(input: &EventEnumDecl) -> syn::Result { fn expand_event_enum( kind: EventKind, var: EventEnumVariation, - events: &[LitStr], + events: &[(LitStr, Path)], attrs: &[Attribute], variants: &[EventEnumVariant], ruma_common: &TokenStream, @@ -120,7 +121,8 @@ fn expand_event_enum( let variant_decls = variants.iter().map(|v| v.decl()); let content: Vec<_> = - events.iter().map(|event| to_event_path(event, kind, var, ruma_common)).collect(); + events.iter().map(|(name, path)| to_event_path(name, path, kind, var)).collect(); + let event_types: Vec<_> = events.iter().map(|(name, _)| name).collect(); let custom_ty = format_ident!("Custom{}Content", kind); @@ -131,11 +133,11 @@ fn expand_event_enum( Ok(quote! { #( #attrs )* #[derive(Clone, Debug)] - #[allow(clippy::large_enum_variant)] + #[allow(clippy::large_enum_variant, unused_qualifications)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] pub enum #ident { #( - #[doc = #events] + #[doc = #event_types] #variant_decls(#content), )* /// An event not defined by the Matrix specification @@ -154,7 +156,7 @@ fn expand_event_enum( fn expand_deserialize_impl( kind: EventKind, var: EventEnumVariation, - events: &[LitStr], + events: &[(LitStr, Path)], variants: &[EventEnumVariant], ruma_common: &TokenStream, ) -> syn::Result { @@ -168,9 +170,11 @@ fn expand_deserialize_impl( quote! { #(#attrs)* } }); let self_variants = variants.iter().map(|v| v.ctor(quote! { Self })); - let content = events.iter().map(|event| to_event_path(event, kind, var, ruma_common)); + let content = events.iter().map(|(name, path)| to_event_path(name, path, kind, var)); + let event_types: Vec<_> = events.iter().map(|(name, _)| name).collect(); Ok(quote! { + #[allow(unused_qualifications)] impl<'de> #serde::de::Deserialize<'de> for #ident { fn deserialize(deserializer: D) -> Result where @@ -184,7 +188,7 @@ fn expand_deserialize_impl( match &*ev_type { #( - #variant_attrs #events => { + #variant_attrs #event_types => { let event = #serde_json::from_str::<#content>(json.get()) .map_err(D::Error::custom)?; Ok(#self_variants(event)) @@ -210,6 +214,7 @@ fn expand_from_impl( let attrs = &variant.attrs; quote! { + #[allow(unused_qualifications)] #[automatically_derived] #(#attrs)* impl ::std::convert::From<#content> for #ty { @@ -288,7 +293,7 @@ fn expand_into_full_event( /// Create a content enum from `EventEnumInput`. fn expand_content_enum( kind: EventKind, - event_types: &[LitStr], + events: &[(LitStr, Path)], attrs: &[Attribute], variants: &[EventEnumVariant], ruma_common: &TokenStream, @@ -301,14 +306,15 @@ fn expand_content_enum( let event_type_enum = kind.to_event_type_enum(); let content: Vec<_> = - event_types.iter().map(|ev| to_event_content_path(kind, ev, None, ruma_common)).collect(); - let event_type_match_arms = event_types.iter().map(|s| { + events.iter().map(|(name, path)| to_event_content_path(kind, name, path, None)).collect(); + let event_type_match_arms = events.iter().map(|(s, _)| { if let Some(prefix) = s.value().strip_suffix(".*") { quote! { _s if _s.starts_with(#prefix) } } else { quote! { #s } } }); + let event_types: Vec<_> = events.iter().map(|(name, _)| name).collect(); let variant_decls = variants.iter().map(|v| v.decl()).collect::>(); let variant_attrs = variants.iter().map(|v| { @@ -561,11 +567,10 @@ fn expand_accessor_methods( fn to_event_path( name: &LitStr, + path: &Path, kind: EventKind, var: EventEnumVariation, - ruma_common: &TokenStream, ) -> TokenStream { - let path = event_module_path(name); let event = m_prefix_name_to_type_name(name).unwrap(); let event_name = if kind == EventKind::ToDevice { assert_eq!(var, EventEnumVariation::None); @@ -573,16 +578,15 @@ fn to_event_path( } else { format_ident!("{}{}Event", var, event) }; - quote! { #ruma_common::events::#( #path )::*::#event_name } + quote! { #path::#event_name } } fn to_event_content_path( kind: EventKind, name: &LitStr, + path: &Path, prefix: Option<&str>, - ruma_common: &TokenStream, ) -> TokenStream { - let path = event_module_path(name); let event = m_prefix_name_to_type_name(name).unwrap(); let content_str = match kind { EventKind::ToDevice => { @@ -592,21 +596,10 @@ fn to_event_content_path( }; quote! { - #ruma_common::events::#( #path )::*::#content_str + #path::#content_str } } -fn event_module_path(name: &LitStr) -> Vec { - let value = name.value(); - let value = value.strip_prefix("m.").unwrap(); - value - .strip_suffix(".*") - .unwrap_or(value) - .split('.') - .map(|s| Ident::new(s, name.span())) - .collect() -} - fn field_return_type(name: &str, ruma_common: &TokenStream) -> TokenStream { match name { "origin_server_ts" => quote! { #ruma_common::MilliSecondsSinceUnixEpoch }, diff --git a/crates/ruma-macros/src/events/event_parse.rs b/crates/ruma-macros/src/events/event_parse.rs index 369358c7..4304219e 100644 --- a/crates/ruma-macros/src/events/event_parse.rs +++ b/crates/ruma-macros/src/events/event_parse.rs @@ -7,7 +7,7 @@ use quote::{format_ident, IdentFragment}; use syn::{ braced, parse::{self, Parse, ParseStream}, - Attribute, Ident, LitStr, Token, + Attribute, Ident, LitStr, Path, Token, }; /// Custom keywords for the `event_enum!` macro @@ -231,11 +231,17 @@ pub fn to_kind_variation(ident: &Ident) -> Option<(EventKind, EventKindVariation pub struct EventEnumEntry { pub attrs: Vec, pub ev_type: LitStr, + pub ev_path: Path, } impl Parse for EventEnumEntry { fn parse(input: ParseStream<'_>) -> syn::Result { - Ok(Self { attrs: input.call(Attribute::parse_outer)?, ev_type: input.parse()? }) + let attrs = input.call(Attribute::parse_outer)?; + let ev_type: LitStr = input.parse()?; + let _: Token![=>] = input.parse()?; + let ev_path = input.call(Path::parse_mod_style)?; + + Ok(Self { attrs, ev_type, ev_path }) } } diff --git a/crates/ruma-macros/src/events/event_type.rs b/crates/ruma-macros/src/events/event_type.rs index 07d141b4..d6f2ceb3 100644 --- a/crates/ruma-macros/src/events/event_type.rs +++ b/crates/ruma-macros/src/events/event_type.rs @@ -1,6 +1,6 @@ use proc_macro2::{Span, TokenStream}; use quote::quote; -use syn::{Ident, LitStr}; +use syn::{parse_quote, Ident, LitStr}; use super::event_parse::{EventEnumEntry, EventEnumInput, EventKind}; @@ -38,6 +38,7 @@ pub fn expand_event_type_enum( let presence = vec![EventEnumEntry { attrs: vec![], ev_type: LitStr::new("m.presence", Span::call_site()), + ev_path: parse_quote! { #ruma_common::events::presence }, }]; let mut all = input.enums.iter().map(|e| &e.events).collect::>(); all.push(&presence);