events: Generate structs without relation for events that can be replaced
This commit is contained in:
parent
6ec7fc09ea
commit
ec853e968a
@ -36,7 +36,7 @@ use super::{
|
|||||||
/// [`MessageType::Audio`]: super::room::message::MessageType::Audio
|
/// [`MessageType::Audio`]: super::room::message::MessageType::Audio
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.audio", kind = MessageLike)]
|
#[ruma_event(type = "m.audio", kind = MessageLike, without_relation)]
|
||||||
pub struct AudioEventContent {
|
pub struct AudioEventContent {
|
||||||
/// The text representation of the message.
|
/// The text representation of the message.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -25,7 +25,7 @@ use super::{
|
|||||||
/// [`MessageType::Emote`]: super::room::message::MessageType::Emote
|
/// [`MessageType::Emote`]: super::room::message::MessageType::Emote
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.emote", kind = MessageLike)]
|
#[ruma_event(type = "m.emote", kind = MessageLike, without_relation)]
|
||||||
pub struct EmoteEventContent {
|
pub struct EmoteEventContent {
|
||||||
/// The message's text content.
|
/// The message's text content.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -34,7 +34,7 @@ use crate::{serde::Base64, OwnedMxcUri};
|
|||||||
/// [`MessageType::File`]: super::room::message::MessageType::File
|
/// [`MessageType::File`]: super::room::message::MessageType::File
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.file", kind = MessageLike)]
|
#[ruma_event(type = "m.file", kind = MessageLike, without_relation)]
|
||||||
pub struct FileEventContent {
|
pub struct FileEventContent {
|
||||||
/// The text representation of the message.
|
/// The text representation of the message.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -31,7 +31,7 @@ use crate::OwnedMxcUri;
|
|||||||
/// [`MessageType::Image`]: super::room::message::MessageType::Image
|
/// [`MessageType::Image`]: super::room::message::MessageType::Image
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.image", kind = MessageLike)]
|
#[ruma_event(type = "m.image", kind = MessageLike, without_relation)]
|
||||||
pub struct ImageEventContent {
|
pub struct ImageEventContent {
|
||||||
/// The text representation of the message.
|
/// The text representation of the message.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -29,7 +29,7 @@ use crate::{MilliSecondsSinceUnixEpoch, PrivOwnedStr};
|
|||||||
/// [`MessageType::Location`]: super::room::message::MessageType::Location
|
/// [`MessageType::Location`]: super::room::message::MessageType::Location
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.location", kind = MessageLike)]
|
#[ruma_event(type = "m.location", kind = MessageLike, without_relation)]
|
||||||
pub struct LocationEventContent {
|
pub struct LocationEventContent {
|
||||||
/// The text representation of the message.
|
/// The text representation of the message.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -81,7 +81,7 @@ use super::room::message::{
|
|||||||
/// [`MessageType::Text`]: super::room::message::MessageType::Text
|
/// [`MessageType::Text`]: super::room::message::MessageType::Text
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.message", kind = MessageLike)]
|
#[ruma_event(type = "m.message", kind = MessageLike, without_relation)]
|
||||||
pub struct MessageEventContent {
|
pub struct MessageEventContent {
|
||||||
/// The message's text content.
|
/// The message's text content.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -25,7 +25,7 @@ use super::{
|
|||||||
/// [`MessageType::Notice`]: super::room::message::MessageType::Notice
|
/// [`MessageType::Notice`]: super::room::message::MessageType::Notice
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.notice", kind = MessageLike)]
|
#[ruma_event(type = "m.notice", kind = MessageLike, without_relation)]
|
||||||
pub struct NoticeEventContent {
|
pub struct NoticeEventContent {
|
||||||
/// The message's text content.
|
/// The message's text content.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -457,6 +457,12 @@ impl From<MessageType> for RoomMessageEventContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RoomMessageEventContent> for MessageType {
|
||||||
|
fn from(content: RoomMessageEventContent) -> Self {
|
||||||
|
content.msgtype
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Message event relationship.
|
/// Message event relationship.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(clippy::manual_non_exhaustive)]
|
#[allow(clippy::manual_non_exhaustive)]
|
||||||
|
@ -32,7 +32,7 @@ use super::{
|
|||||||
/// [`MessageType::Video`]: super::room::message::MessageType::Video
|
/// [`MessageType::Video`]: super::room::message::MessageType::Video
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.video", kind = MessageLike)]
|
#[ruma_event(type = "m.video", kind = MessageLike, without_relation)]
|
||||||
pub struct VideoEventContent {
|
pub struct VideoEventContent {
|
||||||
/// The text representation of the message.
|
/// The text representation of the message.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -29,7 +29,7 @@ use super::{
|
|||||||
/// [`MessageType::Audio`]: super::room::message::MessageType::Audio
|
/// [`MessageType::Audio`]: super::room::message::MessageType::Audio
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.voice", kind = MessageLike)]
|
#[ruma_event(type = "m.voice", kind = MessageLike, without_relation)]
|
||||||
pub struct VoiceEventContent {
|
pub struct VoiceEventContent {
|
||||||
/// The text representation of the message.
|
/// The text representation of the message.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -5,4 +5,6 @@ fn ui() {
|
|||||||
t.compile_fail("tests/events/ui/02-no-event-type.rs");
|
t.compile_fail("tests/events/ui/02-no-event-type.rs");
|
||||||
t.compile_fail("tests/events/ui/03-invalid-event-type.rs");
|
t.compile_fail("tests/events/ui/03-invalid-event-type.rs");
|
||||||
t.pass("tests/events/ui/10-content-wildcard.rs");
|
t.pass("tests/events/ui/10-content-wildcard.rs");
|
||||||
|
t.pass("tests/events/ui/11-content-without-relation-sanity-check.rs");
|
||||||
|
t.compile_fail("tests/events/ui/12-no-relates_to.rs");
|
||||||
}
|
}
|
||||||
|
@ -25,3 +25,4 @@ mod stripped;
|
|||||||
mod to_device;
|
mod to_device;
|
||||||
mod video;
|
mod video;
|
||||||
mod voice;
|
mod voice;
|
||||||
|
mod without_relation;
|
||||||
|
@ -6,7 +6,7 @@ error: no event type attribute found, add `#[ruma_event(type = "any.room.event",
|
|||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `EventContent` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `EventContent` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: expected one of: `type`, `kind`, `custom_redacted`, `state_key_type`, `unsigned_type`, `alias`
|
error: expected one of: `type`, `kind`, `custom_redacted`, `state_key_type`, `unsigned_type`, `alias`, `without_relation`
|
||||||
--> tests/events/ui/03-invalid-event-type.rs:11:14
|
--> tests/events/ui/03-invalid-event-type.rs:11:14
|
||||||
|
|
|
|
||||||
11 | #[ruma_event(event = "m.macro.test", kind = State)]
|
11 | #[ruma_event(event = "m.macro.test", kind = State)]
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
use ruma_macros::EventContent;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
|
||||||
|
#[ruma_event(type = "m.macro.test", kind = MessageLike, without_relation)]
|
||||||
|
pub struct MacroTestContent {
|
||||||
|
pub url: String,
|
||||||
|
pub relates_to: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
10
crates/ruma-common/tests/events/ui/12-no-relates_to.rs
Normal file
10
crates/ruma-common/tests/events/ui/12-no-relates_to.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use ruma_macros::EventContent;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
|
||||||
|
#[ruma_event(type = "m.macro.test", kind = MessageLike, without_relation)]
|
||||||
|
pub struct MacroTestContent {
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,7 @@
|
|||||||
|
error: `without_relation` can only be used on events with a `relates_to` field
|
||||||
|
--> tests/events/ui/12-no-relates_to.rs:4:48
|
||||||
|
|
|
||||||
|
4 | #[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in the derive macro `EventContent` (in Nightly builds, run with -Z macro-backtrace for more info)
|
70
crates/ruma-common/tests/events/without_relation.rs
Normal file
70
crates/ruma-common/tests/events/without_relation.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use assert_matches::assert_matches;
|
||||||
|
use ruma_common::{
|
||||||
|
event_id,
|
||||||
|
events::room::message::{
|
||||||
|
InReplyTo, MessageType, Relation, RoomMessageEventContent,
|
||||||
|
RoomMessageEventContentWithoutRelation,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_room_message_content_without_relation() {
|
||||||
|
let mut content = RoomMessageEventContent::text_plain("Hello, world!");
|
||||||
|
content.relates_to =
|
||||||
|
Some(Relation::Reply { in_reply_to: InReplyTo::new(event_id!("$eventId").to_owned()) });
|
||||||
|
let without_relation = RoomMessageEventContentWithoutRelation::from(content);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unstable-msc3246"))]
|
||||||
|
assert_eq!(
|
||||||
|
to_json_value(&without_relation).unwrap(),
|
||||||
|
json!({
|
||||||
|
"body": "Hello, world!",
|
||||||
|
"msgtype": "m.text",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable-msc3246")]
|
||||||
|
assert_eq!(
|
||||||
|
to_json_value(&without_relation).unwrap(),
|
||||||
|
json!({
|
||||||
|
"body": "Hello, world!",
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"org.matrix.msc1767.text": "Hello, world!",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_room_message_content_without_relation() {
|
||||||
|
let json_data = json!({
|
||||||
|
"body": "Hello, world!",
|
||||||
|
"msgtype": "m.text",
|
||||||
|
});
|
||||||
|
|
||||||
|
let text = assert_matches!(
|
||||||
|
from_json_value::<RoomMessageEventContentWithoutRelation>(json_data),
|
||||||
|
Ok(RoomMessageEventContentWithoutRelation::Text(text)) => text
|
||||||
|
);
|
||||||
|
assert_eq!(text.body, "Hello, world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_room_message_content_without_relation_to_full() {
|
||||||
|
let mut content = RoomMessageEventContent::text_plain("Hello, world!");
|
||||||
|
content.relates_to =
|
||||||
|
Some(Relation::Reply { in_reply_to: InReplyTo::new(event_id!("$eventId").to_owned()) });
|
||||||
|
let new_content =
|
||||||
|
RoomMessageEventContent::from(RoomMessageEventContentWithoutRelation::from(content));
|
||||||
|
|
||||||
|
let (text, relates_to) = assert_matches!(
|
||||||
|
new_content,
|
||||||
|
RoomMessageEventContent {
|
||||||
|
msgtype: MessageType::Text(text),
|
||||||
|
relates_to,
|
||||||
|
..
|
||||||
|
} => (text, relates_to)
|
||||||
|
);
|
||||||
|
assert_eq!(text.body, "Hello, world!");
|
||||||
|
assert_matches!(relates_to, None);
|
||||||
|
}
|
@ -28,6 +28,8 @@ mod kw {
|
|||||||
syn::custom_keyword!(unsigned_type);
|
syn::custom_keyword!(unsigned_type);
|
||||||
// Another type string accepted for deserialization.
|
// Another type string accepted for deserialization.
|
||||||
syn::custom_keyword!(alias);
|
syn::custom_keyword!(alias);
|
||||||
|
// The content has a form without relation.
|
||||||
|
syn::custom_keyword!(without_relation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses struct attributes for `*EventContent` derives.
|
/// Parses struct attributes for `*EventContent` derives.
|
||||||
@ -49,6 +51,9 @@ enum EventStructMeta {
|
|||||||
|
|
||||||
/// Variant that holds alternate event type accepted for deserialization.
|
/// Variant that holds alternate event type accepted for deserialization.
|
||||||
Alias(LitStr),
|
Alias(LitStr),
|
||||||
|
|
||||||
|
/// This attribute signals that a form without relation should be generated.
|
||||||
|
WithoutRelation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventStructMeta {
|
impl EventStructMeta {
|
||||||
@ -114,6 +119,9 @@ impl Parse for EventStructMeta {
|
|||||||
let _: kw::alias = input.parse()?;
|
let _: kw::alias = input.parse()?;
|
||||||
let _: Token![=] = input.parse()?;
|
let _: Token![=] = input.parse()?;
|
||||||
input.parse().map(EventStructMeta::Alias)
|
input.parse().map(EventStructMeta::Alias)
|
||||||
|
} else if lookahead.peek(kw::without_relation) {
|
||||||
|
let _: kw::without_relation = input.parse()?;
|
||||||
|
Ok(EventStructMeta::WithoutRelation)
|
||||||
} else {
|
} else {
|
||||||
Err(lookahead.error())
|
Err(lookahead.error())
|
||||||
}
|
}
|
||||||
@ -174,6 +182,10 @@ impl MetaAttrs {
|
|||||||
fn get_aliases(&self) -> impl Iterator<Item = &LitStr> {
|
fn get_aliases(&self) -> impl Iterator<Item = &LitStr> {
|
||||||
self.0.iter().filter_map(|a| a.get_alias())
|
self.0.iter().filter_map(|a| a.get_alias())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_without_relation(&self) -> bool {
|
||||||
|
self.0.iter().any(|a| matches!(*a, EventStructMeta::WithoutRelation))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for MetaAttrs {
|
impl Parse for MetaAttrs {
|
||||||
@ -320,6 +332,22 @@ pub fn expand_event_content(
|
|||||||
.unwrap_or_else(syn::Error::into_compile_error)
|
.unwrap_or_else(syn::Error::into_compile_error)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let without_relations: Vec<_> =
|
||||||
|
content_attr.iter().filter(|attrs| attrs.has_without_relation()).collect();
|
||||||
|
let event_content_without_relation = match without_relations.as_slice() {
|
||||||
|
[] => None,
|
||||||
|
[_] => Some(
|
||||||
|
generate_event_content_without_relation(ident, fields.clone(), ruma_common)
|
||||||
|
.unwrap_or_else(syn::Error::into_compile_error),
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
return Err(syn::Error::new(
|
||||||
|
Span::call_site(),
|
||||||
|
"multiple without_relation attributes found, there can only be one",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let event_content_impl = generate_event_content_impl(
|
let event_content_impl = generate_event_content_impl(
|
||||||
ident,
|
ident,
|
||||||
fields,
|
fields,
|
||||||
@ -340,6 +368,7 @@ pub fn expand_event_content(
|
|||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#redacted_event_content
|
#redacted_event_content
|
||||||
|
#event_content_without_relation
|
||||||
#event_content_impl
|
#event_content_impl
|
||||||
#static_event_content_impl
|
#static_event_content_impl
|
||||||
#type_aliases
|
#type_aliases
|
||||||
@ -506,6 +535,70 @@ fn generate_redacted_event_content<'a>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_event_content_without_relation<'a>(
|
||||||
|
ident: &Ident,
|
||||||
|
fields: impl Iterator<Item = &'a Field>,
|
||||||
|
ruma_common: &TokenStream,
|
||||||
|
) -> syn::Result<TokenStream> {
|
||||||
|
let serde = quote! { #ruma_common::exports::serde };
|
||||||
|
|
||||||
|
let type_doc = format!(
|
||||||
|
"Form of [`{ident}`] without relation.\n\n\
|
||||||
|
To construct this type, construct a [`{ident}`] and then use one of its `::from() / .into()` methods."
|
||||||
|
);
|
||||||
|
let without_relation_ident = format_ident!("{ident}WithoutRelation");
|
||||||
|
|
||||||
|
let with_relation_fn_doc =
|
||||||
|
format!("Transform `self` into a [`{ident}`] with the given relation.");
|
||||||
|
|
||||||
|
let (relates_to, other_fields) = fields.partition::<Vec<_>, _>(|f| {
|
||||||
|
f.ident.as_ref().filter(|ident| *ident == "relates_to").is_some()
|
||||||
|
});
|
||||||
|
|
||||||
|
let relates_to_type = relates_to.into_iter().next().map(|f| &f.ty).ok_or_else(|| {
|
||||||
|
syn::Error::new(
|
||||||
|
Span::call_site(),
|
||||||
|
"`without_relation` can only be used on events with a `relates_to` field",
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let without_relation_fields = other_fields.iter().flat_map(|f| &f.ident).collect::<Vec<_>>();
|
||||||
|
let without_relation_struct = if other_fields.is_empty() {
|
||||||
|
quote! { ; }
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
{ #( #other_fields, )* }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
#[allow(unused_qualifications)]
|
||||||
|
#[automatically_derived]
|
||||||
|
impl ::std::convert::From<#ident> for #without_relation_ident {
|
||||||
|
fn from(c: #ident) -> Self {
|
||||||
|
Self {
|
||||||
|
#( #without_relation_fields: c.#without_relation_fields, )*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = #type_doc]
|
||||||
|
#[derive(Clone, Debug, #serde::Deserialize, #serde::Serialize)]
|
||||||
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
|
pub struct #without_relation_ident #without_relation_struct
|
||||||
|
|
||||||
|
impl #without_relation_ident {
|
||||||
|
#[doc = #with_relation_fn_doc]
|
||||||
|
pub fn with_relation(self, relates_to: #relates_to_type) -> #ident {
|
||||||
|
#ident {
|
||||||
|
#( #without_relation_fields: self.#without_relation_fields, )*
|
||||||
|
relates_to,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_event_type_aliases(
|
fn generate_event_type_aliases(
|
||||||
event_kind: EventKind,
|
event_kind: EventKind,
|
||||||
ident: &Ident,
|
ident: &Ident,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user