diff --git a/.gitignore b/.gitignore index fa8d85ac..50e961f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ Cargo.lock target + +# trybuild generates a `wip` folder when creating or updating a test +wip diff --git a/Cargo.toml b/Cargo.toml index 87406b3e..ea2a5c32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ strum = { version = "0.18.0", features = ["derive"] } maplit = "1.0.2" matches = "0.1.8" ruma-identifiers = { version = "0.16.2", features = ["rand"] } +trybuild = "1.0.27" [workspace] members = [ diff --git a/ruma-events-macros/src/event_content.rs b/ruma-events-macros/src/event_content.rs index d4aa9b15..223f677b 100644 --- a/ruma-events-macros/src/event_content.rs +++ b/ruma-events-macros/src/event_content.rs @@ -58,10 +58,9 @@ fn expand_room_event(input: DeriveInput) -> syn::Result { content: Box<::serde_json::value::RawValue> ) -> Result { if ev_type != #event_type { - return Err(::ruma_events::InvalidEvent { - kind: ::ruma_events::error::InvalidEventKind::Deserialization, - message: format!("expected `{}` found {}", #event_type, ev_type), - }); + return Err( + ::ruma_events::InvalidEvent::wrong_event_type(#event_type, ev_type) + ); } let ev_json = ::ruma_events::EventJson::from(content); diff --git a/src/error.rs b/src/error.rs index 56b5b0b9..af49bb9e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,17 +11,32 @@ use std::{ /// message and a flag for which type of error was encountered. #[derive(Clone, Debug)] pub struct InvalidEvent { + /// A description of the error that occurred. pub(crate) message: String, + /// The kind of error that occurred. pub(crate) kind: InvalidEventKind, } +/// The kind of error that occurred. #[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum InvalidEventKind { +pub(crate) enum InvalidEventKind { + /// A deserialization error from malformed input. Deserialization, + /// An error occurred validating input according the the matrix spec. Validation, } impl InvalidEvent { + /// Constructor used in the event content macros. + /// + /// This has to be public to allow the macros to be used outside of ruma-events. + #[doc(hidden)] + pub fn wrong_event_type(expected: &str, found: &str) -> Self { + Self { + message: format!("expected `{}` found {}", expected, found), + kind: InvalidEventKind::Deserialization, + } + } /// A message describing why the event is invalid. pub fn message(&self) -> String { self.message.clone() diff --git a/tests/event_content.rs b/tests/event_content.rs new file mode 100644 index 00000000..aacac007 --- /dev/null +++ b/tests/event_content.rs @@ -0,0 +1,7 @@ +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.pass("tests/ui/01-sanity-check.rs"); + t.compile_fail("tests/ui/02-no-event-type.rs"); + t.compile_fail("tests/ui/03-invalid-event-type.rs"); +} diff --git a/tests/ui/01-sanity-check.rs b/tests/ui/01-sanity-check.rs new file mode 100644 index 00000000..613dfd4a --- /dev/null +++ b/tests/ui/01-sanity-check.rs @@ -0,0 +1,10 @@ +use ruma_events_macros::{FromRaw, StateEventContent}; +use serde::Serialize; + +#[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] +#[ruma_event(type = "m.macro.test")] +pub struct MacroTest { + pub url: String, +} + +fn main() {} diff --git a/tests/ui/02-no-event-type.rs b/tests/ui/02-no-event-type.rs new file mode 100644 index 00000000..4ab7bc4e --- /dev/null +++ b/tests/ui/02-no-event-type.rs @@ -0,0 +1,9 @@ +use ruma_events_macros::{FromRaw, StateEventContent}; +use serde::Serialize; + +#[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] +pub struct MacroTest { + pub url: String, +} + +fn main() {} diff --git a/tests/ui/02-no-event-type.stderr b/tests/ui/02-no-event-type.stderr new file mode 100644 index 00000000..f61e62c3 --- /dev/null +++ b/tests/ui/02-no-event-type.stderr @@ -0,0 +1,7 @@ +error: no event type attribute found, add `#[ruma_events(type = "any.room.event")]` below the event content derive + --> $DIR/02-no-event-type.rs:4:44 + | +4 | #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] + | ^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/03-invalid-event-type.rs b/tests/ui/03-invalid-event-type.rs new file mode 100644 index 00000000..a2a5f0f3 --- /dev/null +++ b/tests/ui/03-invalid-event-type.rs @@ -0,0 +1,16 @@ +use ruma_events_macros::{FromRaw, StateEventContent}; +use serde::Serialize; + +#[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] +#[not_ruma_event(type = "m.macro.test")] +pub struct MacroTest { + pub test: String, +} + +#[derive(Clone, Debug, Serialize, StateEventContent)] +#[ruma_event(event = "m.macro.test")] +pub struct MoreMacroTest { + pub test: String, +} + +fn main() {} diff --git a/tests/ui/03-invalid-event-type.stderr b/tests/ui/03-invalid-event-type.stderr new file mode 100644 index 00000000..9532791a --- /dev/null +++ b/tests/ui/03-invalid-event-type.stderr @@ -0,0 +1,19 @@ +error: expected `type` + --> $DIR/03-invalid-event-type.rs:11:14 + | +11 | #[ruma_event(event = "m.macro.test")] + | ^^^^^ + +error: no event type attribute found, add `#[ruma_events(type = "any.room.event")]` below the event content derive + --> $DIR/03-invalid-event-type.rs:4:44 + | +4 | #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] + | ^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find attribute `not_ruma_event` in this scope + --> $DIR/03-invalid-event-type.rs:5:3 + | +5 | #[not_ruma_event(type = "m.macro.test")] + | ^^^^^^^^^^^^^^ help: a derive helper attribute with a similar name exists: `ruma_event`