From 7cd33019c511cc76294d3880c6e968e93f72070b Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Sat, 22 Jan 2022 15:59:13 +0100 Subject: [PATCH 01/12] Support deriving Collection I also added trybuild to test the error messages of derive macro. The macro does not check for name validity as the restrictions will be removed https://github.com/khonsulabs/bonsaidb/issues/143#issuecomment-1019278177. closes #138 partially --- crates/bonsaidb-macros/Cargo.toml | 12 ++- crates/bonsaidb-macros/src/lib.rs | 93 ++++++++++++++++++- crates/bonsaidb-macros/tests/collection.rs | 54 +++++++++++ .../tests/ui/invalid_attribute.rs | 7 ++ .../tests/ui/invalid_attribute.stderr | 5 + .../tests/ui/missing_authority.rs | 7 ++ .../tests/ui/missing_authority.stderr | 7 ++ .../bonsaidb-macros/tests/ui/missing_name.rs | 7 ++ .../tests/ui/missing_name.stderr | 7 ++ 9 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 crates/bonsaidb-macros/tests/collection.rs create mode 100644 crates/bonsaidb-macros/tests/ui/invalid_attribute.rs create mode 100644 crates/bonsaidb-macros/tests/ui/invalid_attribute.stderr create mode 100644 crates/bonsaidb-macros/tests/ui/missing_authority.rs create mode 100644 crates/bonsaidb-macros/tests/ui/missing_authority.stderr create mode 100644 crates/bonsaidb-macros/tests/ui/missing_name.rs create mode 100644 crates/bonsaidb-macros/tests/ui/missing_name.stderr diff --git a/crates/bonsaidb-macros/Cargo.toml b/crates/bonsaidb-macros/Cargo.toml index febe4da18f3..e31499d54d5 100644 --- a/crates/bonsaidb-macros/Cargo.toml +++ b/crates/bonsaidb-macros/Cargo.toml @@ -15,9 +15,17 @@ homepage = "https://bonsaidb.io/" proc-macro = true [dependencies] -syn = "1" -quote = "1" proc-macro-error = "1" +quote = "1" +syn = "1" +trybuild = "1.0.54" [dev-dependencies] compiletest_rs = "0.7" + +[dev-dependencies.bonsaidb] +path = "../bonsaidb/" + +[dev-dependencies.serde] +version = "1.0.133" +features = ["derive"] diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index 858852364fa..fb75f6ea8e1 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -15,7 +15,10 @@ use proc_macro::TokenStream; use proc_macro_error::{abort, abort_call_site, proc_macro_error}; use quote::quote; -use syn::{parse_macro_input, Data, DeriveInput}; +use syn::{ + parse_macro_input, spanned::Spanned, Data, DeriveInput, Lit, Meta, MetaList, MetaNameValue, + NestedMeta, Path, +}; /// Derives the `bonsaidb_core::permissions::Action` trait. #[proc_macro_error] @@ -70,3 +73,91 @@ pub fn permissions_action_derive(input: TokenStream) -> TokenStream { TokenStream::from(expanded) } + +/// Derives the `bonsaidb::core::schema::Collection` trait. +#[proc_macro_error] +/// `#[collection(authority = "Authority", name = "Name", views(a, b, c))]` +#[proc_macro_derive(Collection, attributes(collection))] +pub fn collection_derive(input: TokenStream) -> TokenStream { + let DeriveInput { + attrs, + ident, + generics, + .. + } = parse_macro_input!(input as DeriveInput); + + let mut name: Option = None; + let mut authority: Option = None; + let mut view: Vec = Vec::new(); + + for attibute in attrs { + if attibute.path.is_ident("collection") { + if let Ok(Meta::List(MetaList { nested, .. })) = attibute.parse_meta() { + for item in nested { + match item { + NestedMeta::Meta(Meta::NameValue(MetaNameValue { + path, + lit: Lit::Str(value), + .. + })) if path.is_ident("name") => name = Some(value.value()), + NestedMeta::Meta(Meta::NameValue(MetaNameValue { + path, + lit: Lit::Str(value), + .. + })) if path.is_ident("authority") => authority = Some(value.value()), + NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) + if path.is_ident("views") => + { + view = nested + .into_iter() + .map(|meta| match meta { + NestedMeta::Meta(Meta::Path(path)) => path, + meta => abort!( + meta.span(), + r#"`{}` is not supported here, call `views` like so: `views(SomeView, AnotherView)`"# + ), + }) + .collect(); + } + item => abort!( + item.span(), + r#"Only `authority="some-authority"`, `name="some-name"`, `views(SomeView, AnotherView)` are supported attributes"# + ), + } + } + } + } + } + + let authority = authority.unwrap_or_else(|| { + abort_call_site!( + r#"You need to specify the collection name via `#[collection(authority="authority")]`"# + ) + }); + + let name = name.unwrap_or_else(|| { + abort_call_site!( + r#"You need to specify the collection name via `#[collection(name="name")]`"# + ) + }); + + quote! { + impl ::bonsaidb::core::schema::Collection for #ident #generics { + fn collection_name() -> ::core::result::Result<::bonsaidb::core::schema::CollectionName, ::bonsaidb::core::schema::InvalidNameError> { + ::bonsaidb::core::schema::CollectionName::new(#authority, #name) + } + fn define_views(schema: &mut ::bonsaidb::core::schema::Schematic) -> ::core::result::Result<(), ::bonsaidb::core::Error>{ + #( schema.define_view(#view)?; )* + ::core::result::Result::Ok(()) + } + } + } + .into() +} + +#[test] +fn ui() { + use trybuild::TestCases; + + TestCases::new().compile_fail("tests/ui/*.rs"); +} diff --git a/crates/bonsaidb-macros/tests/collection.rs b/crates/bonsaidb-macros/tests/collection.rs new file mode 100644 index 00000000000..15175566f14 --- /dev/null +++ b/crates/bonsaidb-macros/tests/collection.rs @@ -0,0 +1,54 @@ +use bonsaidb_macros::Collection; + +#[test] +fn name_only() { + #[derive(Collection, Debug)] + #[collection(name = "Name", authority = "Authority")] + struct Test {} +} +#[test] +fn views() { + use bonsaidb::core::schema::{ + CollectionDocument, CollectionViewSchema, DefaultSerialization, DefaultViewSerialization, + InvalidNameError, Name, View, ViewMapResult, + }; + use serde::{Deserialize, Serialize}; + + #[derive(Collection, Debug, Serialize, Deserialize)] + #[collection(name = "Name", authority = "Authority", views(ShapesByNumberOfSides))] + struct Shape { + pub sides: u32, + } + + impl DefaultSerialization for Shape {} + + #[derive(Debug, Clone)] + struct ShapesByNumberOfSides; + + impl View for ShapesByNumberOfSides { + type Collection = Shape; + type Key = u32; + type Value = usize; + + fn name(&self) -> Result { + Name::new("by-number-of-sides") + } + } + + impl CollectionViewSchema for ShapesByNumberOfSides { + type View = Self; + + fn map(&self, document: CollectionDocument) -> ViewMapResult { + Ok(document.emit_key_and_value(document.contents.sides, 1)) + } + } + + impl DefaultViewSerialization for ShapesByNumberOfSides {} +} + +// #[test] +// fn invalid_attribute() { +// #[derive(Collection)] +// #[collection(name = "hi", authority = "hello", "hi")] +// struct Test; +// } diff --git a/crates/bonsaidb-macros/tests/ui/invalid_attribute.rs b/crates/bonsaidb-macros/tests/ui/invalid_attribute.rs new file mode 100644 index 00000000000..8b78d68dcd5 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/invalid_attribute.rs @@ -0,0 +1,7 @@ +use bonsaidb_macros::Collection; + +#[derive(Collection)] +#[collection(name = "hi", authority = "hello", "hi")] +struct Test; + +fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/invalid_attribute.stderr b/crates/bonsaidb-macros/tests/ui/invalid_attribute.stderr new file mode 100644 index 00000000000..1afb88ab008 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/invalid_attribute.stderr @@ -0,0 +1,5 @@ +error: Only `authority="some-authority"`, `name="some-name"`, `views(SomeView, AnotherView)` are supported attributes + --> tests/ui/invalid_attribute.rs:4:48 + | +4 | #[collection(name = "hi", authority = "hello", "hi")] + | ^^^^ diff --git a/crates/bonsaidb-macros/tests/ui/missing_authority.rs b/crates/bonsaidb-macros/tests/ui/missing_authority.rs new file mode 100644 index 00000000000..d1f6987651a --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/missing_authority.rs @@ -0,0 +1,7 @@ +use bonsaidb_macros::Collection; + +#[derive(Collection)] +#[collection(name = "hello")] +struct Test; + +fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/missing_authority.stderr b/crates/bonsaidb-macros/tests/ui/missing_authority.stderr new file mode 100644 index 00000000000..b9e9767b181 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/missing_authority.stderr @@ -0,0 +1,7 @@ +error: You need to specify the collection name via `#[collection(authority="authority")]` + --> tests/ui/missing_authority.rs:3:10 + | +3 | #[derive(Collection)] + | ^^^^^^^^^^ + | + = note: this error originates in the derive macro `Collection` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/bonsaidb-macros/tests/ui/missing_name.rs b/crates/bonsaidb-macros/tests/ui/missing_name.rs new file mode 100644 index 00000000000..9313f4e1710 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/missing_name.rs @@ -0,0 +1,7 @@ +use bonsaidb_macros::Collection; + +#[derive(Collection)] +#[collection(authority = "hello")] +struct Test; + +fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/missing_name.stderr b/crates/bonsaidb-macros/tests/ui/missing_name.stderr new file mode 100644 index 00000000000..ac674dd32e9 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/missing_name.stderr @@ -0,0 +1,7 @@ +error: You need to specify the collection name via `#[collection(name="name")]` + --> tests/ui/missing_name.rs:3:10 + | +3 | #[derive(Collection)] + | ^^^^^^^^^^ + | + = note: this error originates in the derive macro `Collection` (in Nightly builds, run with -Z macro-backtrace for more info) From bc784e02fb4f757b0f6ccfcfb478b66a80c7835c Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Sun, 23 Jan 2022 18:45:27 +0100 Subject: [PATCH 02/12] Moved collection into submodule --- crates/bonsaidb-core/src/schema/mod.rs | 2 ++ crates/bonsaidb-macros/src/lib.rs | 2 +- .../tests/{collection.rs => collection/mod.rs} | 16 +++++++--------- .../{ => collection}/ui/invalid_attribute.rs | 2 +- .../{ => collection}/ui/invalid_attribute.stderr | 2 +- .../{ => collection}/ui/missing_authority.rs | 2 +- .../{ => collection}/ui/missing_authority.stderr | 2 +- .../tests/{ => collection}/ui/missing_name.rs | 2 +- .../{ => collection}/ui/missing_name.stderr | 2 +- crates/bonsaidb-macros/tests/mod.rs | 1 + 10 files changed, 17 insertions(+), 16 deletions(-) rename crates/bonsaidb-macros/tests/{collection.rs => collection/mod.rs} (85%) rename crates/bonsaidb-macros/tests/{ => collection}/ui/invalid_attribute.rs (72%) rename crates/bonsaidb-macros/tests/{ => collection}/ui/invalid_attribute.stderr (82%) rename crates/bonsaidb-macros/tests/{ => collection}/ui/missing_authority.rs (66%) rename crates/bonsaidb-macros/tests/{ => collection}/ui/missing_authority.stderr (84%) rename crates/bonsaidb-macros/tests/{ => collection}/ui/missing_name.rs (68%) rename crates/bonsaidb-macros/tests/{ => collection}/ui/missing_name.stderr (85%) create mode 100644 crates/bonsaidb-macros/tests/mod.rs diff --git a/crates/bonsaidb-core/src/schema/mod.rs b/crates/bonsaidb-core/src/schema/mod.rs index 3bcc6de9033..a908591e303 100644 --- a/crates/bonsaidb-core/src/schema/mod.rs +++ b/crates/bonsaidb-core/src/schema/mod.rs @@ -20,6 +20,8 @@ pub use self::{ }; use crate::Error; +pub use bonsaidb_macros::Collection; + /// Defines a group of collections that are stored into a single database. pub trait Schema: Send + Sync + Debug + 'static { /// Returns the unique [`SchemaName`] for this schema. diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index fb75f6ea8e1..5b37ad994b3 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -159,5 +159,5 @@ pub fn collection_derive(input: TokenStream) -> TokenStream { fn ui() { use trybuild::TestCases; - TestCases::new().compile_fail("tests/ui/*.rs"); + TestCases::new().compile_fail("tests/*/ui/*.rs"); } diff --git a/crates/bonsaidb-macros/tests/collection.rs b/crates/bonsaidb-macros/tests/collection/mod.rs similarity index 85% rename from crates/bonsaidb-macros/tests/collection.rs rename to crates/bonsaidb-macros/tests/collection/mod.rs index 15175566f14..c70fc69fc3f 100644 --- a/crates/bonsaidb-macros/tests/collection.rs +++ b/crates/bonsaidb-macros/tests/collection/mod.rs @@ -1,10 +1,15 @@ -use bonsaidb_macros::Collection; +use bonsaidb::core::schema::Collection; #[test] fn name_only() { #[derive(Collection, Debug)] #[collection(name = "Name", authority = "Authority")] - struct Test {} + struct Test; + + assert_eq!( + Test::collection_name().unwrap(), + bonsaidb::core::schema::CollectionName::new("Authority", "Name").unwrap() + ); } #[test] fn views() { @@ -45,10 +50,3 @@ fn views() { impl DefaultViewSerialization for ShapesByNumberOfSides {} } - -// #[test] -// fn invalid_attribute() { -// #[derive(Collection)] -// #[collection(name = "hi", authority = "hello", "hi")] -// struct Test; -// } diff --git a/crates/bonsaidb-macros/tests/ui/invalid_attribute.rs b/crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.rs similarity index 72% rename from crates/bonsaidb-macros/tests/ui/invalid_attribute.rs rename to crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.rs index 8b78d68dcd5..51ab720c94e 100644 --- a/crates/bonsaidb-macros/tests/ui/invalid_attribute.rs +++ b/crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.rs @@ -1,4 +1,4 @@ -use bonsaidb_macros::Collection; +use bonsaidb::core::schema::Collection; #[derive(Collection)] #[collection(name = "hi", authority = "hello", "hi")] diff --git a/crates/bonsaidb-macros/tests/ui/invalid_attribute.stderr b/crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.stderr similarity index 82% rename from crates/bonsaidb-macros/tests/ui/invalid_attribute.stderr rename to crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.stderr index 1afb88ab008..864d1728bcb 100644 --- a/crates/bonsaidb-macros/tests/ui/invalid_attribute.stderr +++ b/crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.stderr @@ -1,5 +1,5 @@ error: Only `authority="some-authority"`, `name="some-name"`, `views(SomeView, AnotherView)` are supported attributes - --> tests/ui/invalid_attribute.rs:4:48 + --> tests/collection/ui/invalid_attribute.rs:4:48 | 4 | #[collection(name = "hi", authority = "hello", "hi")] | ^^^^ diff --git a/crates/bonsaidb-macros/tests/ui/missing_authority.rs b/crates/bonsaidb-macros/tests/collection/ui/missing_authority.rs similarity index 66% rename from crates/bonsaidb-macros/tests/ui/missing_authority.rs rename to crates/bonsaidb-macros/tests/collection/ui/missing_authority.rs index d1f6987651a..c55793618d3 100644 --- a/crates/bonsaidb-macros/tests/ui/missing_authority.rs +++ b/crates/bonsaidb-macros/tests/collection/ui/missing_authority.rs @@ -1,4 +1,4 @@ -use bonsaidb_macros::Collection; +use bonsaidb::core::schema::Collection; #[derive(Collection)] #[collection(name = "hello")] diff --git a/crates/bonsaidb-macros/tests/ui/missing_authority.stderr b/crates/bonsaidb-macros/tests/collection/ui/missing_authority.stderr similarity index 84% rename from crates/bonsaidb-macros/tests/ui/missing_authority.stderr rename to crates/bonsaidb-macros/tests/collection/ui/missing_authority.stderr index b9e9767b181..3776f3b6c81 100644 --- a/crates/bonsaidb-macros/tests/ui/missing_authority.stderr +++ b/crates/bonsaidb-macros/tests/collection/ui/missing_authority.stderr @@ -1,5 +1,5 @@ error: You need to specify the collection name via `#[collection(authority="authority")]` - --> tests/ui/missing_authority.rs:3:10 + --> tests/collection/ui/missing_authority.rs:3:10 | 3 | #[derive(Collection)] | ^^^^^^^^^^ diff --git a/crates/bonsaidb-macros/tests/ui/missing_name.rs b/crates/bonsaidb-macros/tests/collection/ui/missing_name.rs similarity index 68% rename from crates/bonsaidb-macros/tests/ui/missing_name.rs rename to crates/bonsaidb-macros/tests/collection/ui/missing_name.rs index 9313f4e1710..c22fa1e1988 100644 --- a/crates/bonsaidb-macros/tests/ui/missing_name.rs +++ b/crates/bonsaidb-macros/tests/collection/ui/missing_name.rs @@ -1,4 +1,4 @@ -use bonsaidb_macros::Collection; +use bonsaidb::core::schema::Collection; #[derive(Collection)] #[collection(authority = "hello")] diff --git a/crates/bonsaidb-macros/tests/ui/missing_name.stderr b/crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr similarity index 85% rename from crates/bonsaidb-macros/tests/ui/missing_name.stderr rename to crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr index ac674dd32e9..c1655ea648f 100644 --- a/crates/bonsaidb-macros/tests/ui/missing_name.stderr +++ b/crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr @@ -1,5 +1,5 @@ error: You need to specify the collection name via `#[collection(name="name")]` - --> tests/ui/missing_name.rs:3:10 + --> tests/collection/ui/missing_name.rs:3:10 | 3 | #[derive(Collection)] | ^^^^^^^^^^ diff --git a/crates/bonsaidb-macros/tests/mod.rs b/crates/bonsaidb-macros/tests/mod.rs new file mode 100644 index 00000000000..0451506bff5 --- /dev/null +++ b/crates/bonsaidb-macros/tests/mod.rs @@ -0,0 +1 @@ +mod collection; From 4b5e5e50cea6e84e4ffe631c8cf24cf6cffe618f Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Mon, 24 Jan 2022 05:38:02 +0100 Subject: [PATCH 03/12] Derive serialization --- crates/bonsaidb-macros/Cargo.toml | 1 + crates/bonsaidb-macros/src/lib.rs | 59 ++++++++++++++++--- .../bonsaidb-macros/tests/collection/mod.rs | 51 ++++++++++++++-- .../tests/collection/ui/missing_name.stderr | 2 +- 4 files changed, 100 insertions(+), 13 deletions(-) diff --git a/crates/bonsaidb-macros/Cargo.toml b/crates/bonsaidb-macros/Cargo.toml index e31499d54d5..95162773e92 100644 --- a/crates/bonsaidb-macros/Cargo.toml +++ b/crates/bonsaidb-macros/Cargo.toml @@ -22,6 +22,7 @@ trybuild = "1.0.54" [dev-dependencies] compiletest_rs = "0.7" +transmog-bincode = "0.1.0-dev.2" [dev-dependencies.bonsaidb] path = "../bonsaidb/" diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index 5b37ad994b3..d60b6ed3ff7 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -12,9 +12,8 @@ )] #![allow(clippy::option_if_let_else)] -use proc_macro::TokenStream; use proc_macro_error::{abort, abort_call_site, proc_macro_error}; -use quote::quote; +use quote::{__private::TokenStream, quote}; use syn::{ parse_macro_input, spanned::Spanned, Data, DeriveInput, Lit, Meta, MetaList, MetaNameValue, NestedMeta, Path, @@ -23,7 +22,7 @@ use syn::{ /// Derives the `bonsaidb_core::permissions::Action` trait. #[proc_macro_error] #[proc_macro_derive(Action)] -pub fn permissions_action_derive(input: TokenStream) -> TokenStream { +pub fn permissions_action_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse_macro_input!(input as DeriveInput); let name = input.ident; @@ -71,14 +70,14 @@ pub fn permissions_action_derive(input: TokenStream) -> TokenStream { } }; - TokenStream::from(expanded) + expanded.into() } /// Derives the `bonsaidb::core::schema::Collection` trait. #[proc_macro_error] /// `#[collection(authority = "Authority", name = "Name", views(a, b, c))]` #[proc_macro_derive(Collection, attributes(collection))] -pub fn collection_derive(input: TokenStream) -> TokenStream { +pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let DeriveInput { attrs, ident, @@ -89,11 +88,13 @@ pub fn collection_derive(input: TokenStream) -> TokenStream { let mut name: Option = None; let mut authority: Option = None; let mut view: Vec = Vec::new(); + let mut serialization: Option = None; for attibute in attrs { if attibute.path.is_ident("collection") { if let Ok(Meta::List(MetaList { nested, .. })) = attibute.parse_meta() { for item in nested { + let span = item.span(); match item { NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, @@ -105,6 +106,30 @@ pub fn collection_derive(input: TokenStream) -> TokenStream { lit: Lit::Str(value), .. })) if path.is_ident("authority") => authority = Some(value.value()), + NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) + if path.is_ident("serialization") => + { + match nested.len() { + 0 => abort!( + span, + r#"You need to pass either a format type or `None` to `serialization`: `serialization(Format)`"#, + ), + 2.. => abort!( + span, + r#"You can only specify a single format with `serialization` like so: `serialization(Format)`"#, + ), + _ => (), + } + serialization = nested + .into_iter() + .map(|meta| match meta { + NestedMeta::Meta(Meta::Path(path)) => path, + meta => abort!( + meta.span(), + r#"`{}` is not supported here, call `serialization` like so: `serialization(Format)`"# + ), + }).next(); + } NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) if path.is_ident("views") => { @@ -137,12 +162,31 @@ pub fn collection_derive(input: TokenStream) -> TokenStream { let name = name.unwrap_or_else(|| { abort_call_site!( - r#"You need to specify the collection name via `#[collection(name="name")]`"# + r#"You need to specify the collection authority via `#[collection(name="name")]`"# ) }); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let serialization = match serialization { + Some(serialization) if serialization.is_ident("None") => TokenStream::new(), + Some(serialization) => quote! { + impl #impl_generics ::bonsaidb::core::schema::SerializedCollection for #ident #ty_generics #where_clause { + type Contents = #ident #ty_generics; + type Format = #serialization; + + fn format() -> Self::Format { + #serialization::default() + } + } + }, + None => quote! { + impl #impl_generics ::bonsaidb::core::schema::DefaultSerialization for #ident #ty_generics #where_clause {} + }, + }; + quote! { - impl ::bonsaidb::core::schema::Collection for #ident #generics { + impl #impl_generics ::bonsaidb::core::schema::Collection for #ident #ty_generics #where_clause { fn collection_name() -> ::core::result::Result<::bonsaidb::core::schema::CollectionName, ::bonsaidb::core::schema::InvalidNameError> { ::bonsaidb::core::schema::CollectionName::new(#authority, #name) } @@ -151,6 +195,7 @@ pub fn collection_derive(input: TokenStream) -> TokenStream { ::core::result::Result::Ok(()) } } + #serialization } .into() } diff --git a/crates/bonsaidb-macros/tests/collection/mod.rs b/crates/bonsaidb-macros/tests/collection/mod.rs index c70fc69fc3f..eb1d18439fe 100644 --- a/crates/bonsaidb-macros/tests/collection/mod.rs +++ b/crates/bonsaidb-macros/tests/collection/mod.rs @@ -1,20 +1,23 @@ -use bonsaidb::core::schema::Collection; +use core::fmt::Debug; + +use bonsaidb::core::schema::SerializedCollection; #[test] fn name_only() { + use bonsaidb::core::schema::Collection; #[derive(Collection, Debug)] #[collection(name = "Name", authority = "Authority")] - struct Test; + struct Test(T); assert_eq!( - Test::collection_name().unwrap(), + Test::::collection_name().unwrap(), bonsaidb::core::schema::CollectionName::new("Authority", "Name").unwrap() ); } #[test] fn views() { use bonsaidb::core::schema::{ - CollectionDocument, CollectionViewSchema, DefaultSerialization, DefaultViewSerialization, + Collection, CollectionDocument, CollectionViewSchema, DefaultViewSerialization, InvalidNameError, Name, View, ViewMapResult, }; use serde::{Deserialize, Serialize}; @@ -25,7 +28,7 @@ fn views() { pub sides: u32, } - impl DefaultSerialization for Shape {} + // TODO somehow test views #[derive(Debug, Clone)] struct ShapesByNumberOfSides; @@ -50,3 +53,41 @@ fn views() { impl DefaultViewSerialization for ShapesByNumberOfSides {} } + +#[test] +fn serialization() { + use bonsaidb::core::schema::Collection; + use serde::{Deserialize, Serialize}; + + #[derive(Collection, Debug, Deserialize, Serialize)] + #[collection( + name = "Name", + authority = "Authority", + serialization(transmog_bincode::Bincode) + )] + struct Test; + + assert_eq!( + Test::collection_name().unwrap(), + bonsaidb::core::schema::CollectionName::new("Authority", "Name").unwrap() + ); + + let _: transmog_bincode::Bincode = Test::format(); +} + +#[test] +fn serialization_none() { + use bonsaidb::core::schema::{Collection, DefaultSerialization}; + use serde::{Deserialize, Serialize}; + + #[derive(Collection, Debug, Deserialize, Serialize)] + #[collection(name = "Name", authority = "Authority", serialization(None))] + struct Test; + + impl DefaultSerialization for Test {} + + assert_eq!( + Test::collection_name().unwrap(), + bonsaidb::core::schema::CollectionName::new("Authority", "Name").unwrap() + ); +} diff --git a/crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr b/crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr index c1655ea648f..5e35f90b769 100644 --- a/crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr +++ b/crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr @@ -1,4 +1,4 @@ -error: You need to specify the collection name via `#[collection(name="name")]` +error: You need to specify the collection authority via `#[collection(name="name")]` --> tests/collection/ui/missing_name.rs:3:10 | 3 | #[derive(Collection)] From 4aa79ccff015f4aab07cf6754682df170ebb820c Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Mon, 24 Jan 2022 06:14:37 +0100 Subject: [PATCH 04/12] remove NameErrors --- crates/bonsaidb-macros/src/lib.rs | 58 +------------------ .../bonsaidb-macros/tests/collection/mod.rs | 18 +++--- 2 files changed, 11 insertions(+), 65 deletions(-) diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index d60b6ed3ff7..ce9a104f19a 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -15,64 +15,10 @@ use proc_macro_error::{abort, abort_call_site, proc_macro_error}; use quote::{__private::TokenStream, quote}; use syn::{ - parse_macro_input, spanned::Spanned, Data, DeriveInput, Lit, Meta, MetaList, MetaNameValue, + parse_macro_input, spanned::Spanned, DeriveInput, Lit, Meta, MetaList, MetaNameValue, NestedMeta, Path, }; -/// Derives the `bonsaidb_core::permissions::Action` trait. -#[proc_macro_error] -#[proc_macro_derive(Action)] -pub fn permissions_action_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - - let name = input.ident; - - let mut fields = Vec::new(); - match input.data { - Data::Enum(data) => { - for variant in data.variants.iter() { - let ident = variant.ident.clone(); - let ident_as_string = ident.to_string(); - match variant.fields.len() { - 0 => { - fields.push(quote! { Self::#ident => ActionName(vec![::std::borrow::Cow::Borrowed(#ident_as_string)]) }); - } - 1 => { - fields.push(quote! { - Self::#ident(subaction) => { - let mut name = Action::name(subaction); - name.0.insert(0, ::std::borrow::Cow::Borrowed(#ident_as_string)); - name - } - }); - } - _ => { - abort!( - variant.ident, - "For derive(Action), all enum variants may have at most 1 field" - ) - } - } - } - } - _ => abort_call_site!("Action can only be derived for an enum."), - } - - let expanded = quote! { - impl Action for #name { - fn name(&self) -> ActionName { - match self { - #( - #fields - ),* - } - } - } - }; - - expanded.into() -} - /// Derives the `bonsaidb::core::schema::Collection` trait. #[proc_macro_error] /// `#[collection(authority = "Authority", name = "Name", views(a, b, c))]` @@ -187,7 +133,7 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr quote! { impl #impl_generics ::bonsaidb::core::schema::Collection for #ident #ty_generics #where_clause { - fn collection_name() -> ::core::result::Result<::bonsaidb::core::schema::CollectionName, ::bonsaidb::core::schema::InvalidNameError> { + fn collection_name() -> ::bonsaidb::core::schema::CollectionName { ::bonsaidb::core::schema::CollectionName::new(#authority, #name) } fn define_views(schema: &mut ::bonsaidb::core::schema::Schematic) -> ::core::result::Result<(), ::bonsaidb::core::Error>{ diff --git a/crates/bonsaidb-macros/tests/collection/mod.rs b/crates/bonsaidb-macros/tests/collection/mod.rs index eb1d18439fe..d262a23f08f 100644 --- a/crates/bonsaidb-macros/tests/collection/mod.rs +++ b/crates/bonsaidb-macros/tests/collection/mod.rs @@ -10,15 +10,15 @@ fn name_only() { struct Test(T); assert_eq!( - Test::::collection_name().unwrap(), - bonsaidb::core::schema::CollectionName::new("Authority", "Name").unwrap() + Test::::collection_name(), + bonsaidb::core::schema::CollectionName::new("Authority", "Name") ); } #[test] fn views() { use bonsaidb::core::schema::{ - Collection, CollectionDocument, CollectionViewSchema, DefaultViewSerialization, - InvalidNameError, Name, View, ViewMapResult, + Collection, CollectionDocument, CollectionViewSchema, DefaultViewSerialization, Name, View, + ViewMapResult, }; use serde::{Deserialize, Serialize}; @@ -38,7 +38,7 @@ fn views() { type Key = u32; type Value = usize; - fn name(&self) -> Result { + fn name(&self) -> Name { Name::new("by-number-of-sides") } } @@ -68,8 +68,8 @@ fn serialization() { struct Test; assert_eq!( - Test::collection_name().unwrap(), - bonsaidb::core::schema::CollectionName::new("Authority", "Name").unwrap() + Test::collection_name(), + bonsaidb::core::schema::CollectionName::new("Authority", "Name") ); let _: transmog_bincode::Bincode = Test::format(); @@ -87,7 +87,7 @@ fn serialization_none() { impl DefaultSerialization for Test {} assert_eq!( - Test::collection_name().unwrap(), - bonsaidb::core::schema::CollectionName::new("Authority", "Name").unwrap() + Test::collection_name(), + bonsaidb::core::schema::CollectionName::new("Authority", "Name") ); } From c8db61a1ab00254a0969ac90d5ed4306f01be81f Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Wed, 2 Feb 2022 18:26:33 +0100 Subject: [PATCH 05/12] WIP --- crates/bonsaidb-core/src/schema/mod.rs | 2 +- crates/bonsaidb-macros/Cargo.toml | 1 + crates/bonsaidb-macros/src/lib.rs | 182 +++++++++++++++++- .../{collection/mod.rs => collection.rs} | 3 +- crates/bonsaidb-macros/tests/mod.rs | 1 - .../ui => ui/collection}/invalid_attribute.rs | 0 .../collection}/invalid_attribute.stderr | 2 +- .../ui => ui/collection}/missing_authority.rs | 0 .../collection}/missing_authority.stderr | 2 +- .../ui => ui/collection}/missing_name.rs | 0 .../ui => ui/collection}/missing_name.stderr | 2 +- .../tests/ui/view/invalid_attribute.rs | 7 + .../tests/ui/view/invalid_attribute.stderr | 5 + .../tests/ui/view/missing_authority.rs | 7 + .../tests/ui/view/missing_authority.stderr | 7 + .../tests/ui/view/missing_name.rs | 7 + .../tests/ui/view/missing_name.stderr | 7 + crates/bonsaidb-macros/tests/view.rs | 16 ++ 18 files changed, 235 insertions(+), 16 deletions(-) rename crates/bonsaidb-macros/tests/{collection/mod.rs => collection.rs} (97%) delete mode 100644 crates/bonsaidb-macros/tests/mod.rs rename crates/bonsaidb-macros/tests/{collection/ui => ui/collection}/invalid_attribute.rs (100%) rename crates/bonsaidb-macros/tests/{collection/ui => ui/collection}/invalid_attribute.stderr (82%) rename crates/bonsaidb-macros/tests/{collection/ui => ui/collection}/missing_authority.rs (100%) rename crates/bonsaidb-macros/tests/{collection/ui => ui/collection}/missing_authority.stderr (84%) rename crates/bonsaidb-macros/tests/{collection/ui => ui/collection}/missing_name.rs (100%) rename crates/bonsaidb-macros/tests/{collection/ui => ui/collection}/missing_name.stderr (85%) create mode 100644 crates/bonsaidb-macros/tests/ui/view/invalid_attribute.rs create mode 100644 crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr create mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_authority.rs create mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_authority.stderr create mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_name.rs create mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_name.stderr create mode 100644 crates/bonsaidb-macros/tests/view.rs diff --git a/crates/bonsaidb-core/src/schema/mod.rs b/crates/bonsaidb-core/src/schema/mod.rs index a908591e303..c16b1487bfa 100644 --- a/crates/bonsaidb-core/src/schema/mod.rs +++ b/crates/bonsaidb-core/src/schema/mod.rs @@ -20,7 +20,7 @@ pub use self::{ }; use crate::Error; -pub use bonsaidb_macros::Collection; +pub use bonsaidb_macros::{Collection, View}; /// Defines a group of collections that are stored into a single database. pub trait Schema: Send + Sync + Debug + 'static { diff --git a/crates/bonsaidb-macros/Cargo.toml b/crates/bonsaidb-macros/Cargo.toml index 95162773e92..bf9aea15c09 100644 --- a/crates/bonsaidb-macros/Cargo.toml +++ b/crates/bonsaidb-macros/Cargo.toml @@ -16,6 +16,7 @@ proc-macro = true [dependencies] proc-macro-error = "1" +proc-macro2 = "1.0.36" quote = "1" syn = "1" trybuild = "1.0.54" diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index ce9a104f19a..e9bfd95ea7e 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -10,13 +10,19 @@ future_incompatible, rust_2018_idioms, )] -#![allow(clippy::option_if_let_else)] +#![cfg_attr(doc, deny(rustdoc::all))] -use proc_macro_error::{abort, abort_call_site, proc_macro_error}; -use quote::{__private::TokenStream, quote}; +use proc_macro2::{Spacing, TokenStream}; +use proc_macro_error::{abort, abort_call_site, proc_macro_error, ResultExt}; +use quote::quote; use syn::{ - parse_macro_input, spanned::Spanned, DeriveInput, Lit, Meta, MetaList, MetaNameValue, - NestedMeta, Path, + parse::{Parse, ParseStream}, + parse_macro_input, + punctuated::Punctuated, + spanned::Spanned, + token::Paren, + DeriveInput, Error, Ident, Lit, LitStr, Meta, MetaList, MetaNameValue, NestedMeta, Path, + Result, Type, TypeTuple, }; /// Derives the `bonsaidb::core::schema::Collection` trait. @@ -31,9 +37,10 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr .. } = parse_macro_input!(input as DeriveInput); + let mut name: Option = None; let mut authority: Option = None; - let mut view: Vec = Vec::new(); + let mut views: Vec = Vec::new(); let mut serialization: Option = None; for attibute in attrs { @@ -79,7 +86,7 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) if path.is_ident("views") => { - view = nested + views = nested .into_iter() .map(|meta| match meta { NestedMeta::Meta(Meta::Path(path)) => path, @@ -137,7 +144,7 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr ::bonsaidb::core::schema::CollectionName::new(#authority, #name) } fn define_views(schema: &mut ::bonsaidb::core::schema::Schematic) -> ::core::result::Result<(), ::bonsaidb::core::Error>{ - #( schema.define_view(#view)?; )* + #( schema.define_view(#views)?; )* ::core::result::Result::Ok(()) } } @@ -146,9 +153,166 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr .into() } +#[derive(Debug, Clone, Default)] +struct ViewAttribute { + collection: Option, + key: Option, + name: Option, + value: Option, +} + +impl ViewAttribute { + pub fn extend_with(&mut self, other: Self) -> Result<()> { + match (&self.collection, other.collection) { + (None, value @ Some(_)) => self.collection = value, + (Some(first), Some(second)) => { + let mut error = + Error::new_spanned(first, "`collection` type is specified multiple times"); + error.combine(Error::new_spanned( + second, + "`collection` type was already specified", + )); + return Err(error); + } + _ => (), + } + match (&self.key, other.key) { + (None, value @ Some(_)) => self.key = value, + (Some(first), Some(second)) => { + let mut error = Error::new_spanned(first, "`key` type is specified multiple times"); + error.combine(Error::new_spanned( + second, + "`key` type was already specified", + )); + return Err(error); + } + _ => (), + } + match (&self.name, other.name) { + (None, value @ Some(_)) => self.name = value, + (Some(first), Some(second)) => { + let mut error = + Error::new_spanned(first, "`name` type is specified multiple times"); + error.combine(Error::new_spanned( + second, + "`name` type was already specified", + )); + return Err(error); + } + _ => (), + } + Ok(()) + } +} + +impl Parse for ViewAttribute { + fn parse(input: ParseStream<'_>) -> Result { + let mut view_attribute = Self::default(); + loop { + let variable = Ident::parse(input)?; + + // Parse `=` + input.step(|cursor| match cursor.punct() { + Some((punct, rest)) + if punct.as_char() == '=' && punct.spacing() == Spacing::Alone => + { + Ok(((), rest)) + } + _ => Err(cursor.error("Expected assignment `=`")), + })?; + + match variable.to_string().as_str() { + "collection" => { + view_attribute.collection = Some(input.parse()?); + } + "key" => { + view_attribute.key = Some(input.parse()?); + } + "name" => { + view_attribute.name = Some(input.parse()?); + } + _ => { + return Err(Error::new( + variable.span(), + "Expected either `collection`, `key` or `name`", + )) + } + } + + if input.is_empty() { + break; + } + + // Parse `,` + input.step(|cursor| match cursor.punct() { + Some((punct, rest)) if punct.as_char() == ',' => Ok(((), rest)), + _ => Err(cursor.error("Expected assignment `=`")), + })?; + } + Ok(view_attribute) + } +} + +/// Derives the `bonsaidb::core::schema::View` trait. +#[proc_macro_error] +/// `#[view(collection(CollectionType), key(KeyType), value(ValueType), name = "by-name", version = 0)]` +#[proc_macro_derive(View, attributes(view))] +pub fn view_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let DeriveInput { + attrs, + ident, + generics, + .. + } = parse_macro_input!(input as DeriveInput); + + let mut attributes = ViewAttribute::default(); + + for attibute in attrs { + if attibute.path.is_ident("view") { + attributes + .extend_with(attibute.parse_args().unwrap_or_abort()) + .unwrap_or_abort(); + } + } + + let collection = attributes.collection.unwrap_or_else(|| { + abort_call_site!( + r#"You need to specify the collection type via `#[view(collection = CollectionType)]`"# + ) + }); + let key = attributes.key.unwrap_or_else(|| { + abort_call_site!(r#"You need to specify the key type via `#[view(key = KeyType)]`"#) + }); + let value = attributes.value.unwrap_or_else(|| { + Type::Tuple(TypeTuple { + paren_token: Paren::default(), + elems: Punctuated::new(), + }) + }); + let name = attributes + .name + .as_ref() + .map_or_else(|| ident.to_string(), LitStr::value); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + impl #impl_generics ::bonsaidb::core::schema::View for #ident #ty_generics #where_clause { + type Collection = #collection; + type Key = #key; + type Value = #value; + + fn name(&self) -> ::bonsaidb::core::schema::Name { + ::bonsaidb::core::schema::Name::new(#name) + } + } + } + .into() +} + #[test] fn ui() { use trybuild::TestCases; - TestCases::new().compile_fail("tests/*/ui/*.rs"); + TestCases::new().compile_fail("tests/ui/*/*.rs"); } diff --git a/crates/bonsaidb-macros/tests/collection/mod.rs b/crates/bonsaidb-macros/tests/collection.rs similarity index 97% rename from crates/bonsaidb-macros/tests/collection/mod.rs rename to crates/bonsaidb-macros/tests/collection.rs index d262a23f08f..3dbb0941d7d 100644 --- a/crates/bonsaidb-macros/tests/collection/mod.rs +++ b/crates/bonsaidb-macros/tests/collection.rs @@ -1,7 +1,5 @@ use core::fmt::Debug; -use bonsaidb::core::schema::SerializedCollection; - #[test] fn name_only() { use bonsaidb::core::schema::Collection; @@ -57,6 +55,7 @@ fn views() { #[test] fn serialization() { use bonsaidb::core::schema::Collection; + use bonsaidb::core::schema::SerializedCollection; use serde::{Deserialize, Serialize}; #[derive(Collection, Debug, Deserialize, Serialize)] diff --git a/crates/bonsaidb-macros/tests/mod.rs b/crates/bonsaidb-macros/tests/mod.rs deleted file mode 100644 index 0451506bff5..00000000000 --- a/crates/bonsaidb-macros/tests/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod collection; diff --git a/crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.rs b/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.rs similarity index 100% rename from crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.rs rename to crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.rs diff --git a/crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.stderr b/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.stderr similarity index 82% rename from crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.stderr rename to crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.stderr index 864d1728bcb..aa47df43536 100644 --- a/crates/bonsaidb-macros/tests/collection/ui/invalid_attribute.stderr +++ b/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.stderr @@ -1,5 +1,5 @@ error: Only `authority="some-authority"`, `name="some-name"`, `views(SomeView, AnotherView)` are supported attributes - --> tests/collection/ui/invalid_attribute.rs:4:48 + --> tests/ui/collection/invalid_attribute.rs:4:48 | 4 | #[collection(name = "hi", authority = "hello", "hi")] | ^^^^ diff --git a/crates/bonsaidb-macros/tests/collection/ui/missing_authority.rs b/crates/bonsaidb-macros/tests/ui/collection/missing_authority.rs similarity index 100% rename from crates/bonsaidb-macros/tests/collection/ui/missing_authority.rs rename to crates/bonsaidb-macros/tests/ui/collection/missing_authority.rs diff --git a/crates/bonsaidb-macros/tests/collection/ui/missing_authority.stderr b/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr similarity index 84% rename from crates/bonsaidb-macros/tests/collection/ui/missing_authority.stderr rename to crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr index 3776f3b6c81..14543cb7165 100644 --- a/crates/bonsaidb-macros/tests/collection/ui/missing_authority.stderr +++ b/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr @@ -1,5 +1,5 @@ error: You need to specify the collection name via `#[collection(authority="authority")]` - --> tests/collection/ui/missing_authority.rs:3:10 + --> tests/ui/collection/missing_authority.rs:3:10 | 3 | #[derive(Collection)] | ^^^^^^^^^^ diff --git a/crates/bonsaidb-macros/tests/collection/ui/missing_name.rs b/crates/bonsaidb-macros/tests/ui/collection/missing_name.rs similarity index 100% rename from crates/bonsaidb-macros/tests/collection/ui/missing_name.rs rename to crates/bonsaidb-macros/tests/ui/collection/missing_name.rs diff --git a/crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr b/crates/bonsaidb-macros/tests/ui/collection/missing_name.stderr similarity index 85% rename from crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr rename to crates/bonsaidb-macros/tests/ui/collection/missing_name.stderr index 5e35f90b769..a72e0ee64fd 100644 --- a/crates/bonsaidb-macros/tests/collection/ui/missing_name.stderr +++ b/crates/bonsaidb-macros/tests/ui/collection/missing_name.stderr @@ -1,5 +1,5 @@ error: You need to specify the collection authority via `#[collection(name="name")]` - --> tests/collection/ui/missing_name.rs:3:10 + --> tests/ui/collection/missing_name.rs:3:10 | 3 | #[derive(Collection)] | ^^^^^^^^^^ diff --git a/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.rs b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.rs new file mode 100644 index 00000000000..51ab720c94e --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.rs @@ -0,0 +1,7 @@ +use bonsaidb::core::schema::Collection; + +#[derive(Collection)] +#[collection(name = "hi", authority = "hello", "hi")] +struct Test; + +fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr new file mode 100644 index 00000000000..66f3195eb1d --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr @@ -0,0 +1,5 @@ +error: Only `authority="some-authority"`, `name="some-name"`, `views(SomeView, AnotherView)` are supported attributes + --> tests/ui/view/invalid_attribute.rs:4:48 + | +4 | #[collection(name = "hi", authority = "hello", "hi")] + | ^^^^ diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_authority.rs b/crates/bonsaidb-macros/tests/ui/view/missing_authority.rs new file mode 100644 index 00000000000..c55793618d3 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/missing_authority.rs @@ -0,0 +1,7 @@ +use bonsaidb::core::schema::Collection; + +#[derive(Collection)] +#[collection(name = "hello")] +struct Test; + +fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_authority.stderr b/crates/bonsaidb-macros/tests/ui/view/missing_authority.stderr new file mode 100644 index 00000000000..5493a630caa --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/missing_authority.stderr @@ -0,0 +1,7 @@ +error: You need to specify the collection name via `#[collection(authority="authority")]` + --> tests/ui/view/missing_authority.rs:3:10 + | +3 | #[derive(Collection)] + | ^^^^^^^^^^ + | + = note: this error originates in the derive macro `Collection` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_name.rs b/crates/bonsaidb-macros/tests/ui/view/missing_name.rs new file mode 100644 index 00000000000..c22fa1e1988 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/missing_name.rs @@ -0,0 +1,7 @@ +use bonsaidb::core::schema::Collection; + +#[derive(Collection)] +#[collection(authority = "hello")] +struct Test; + +fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_name.stderr b/crates/bonsaidb-macros/tests/ui/view/missing_name.stderr new file mode 100644 index 00000000000..2dfa0934e95 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/missing_name.stderr @@ -0,0 +1,7 @@ +error: You need to specify the collection authority via `#[collection(name="name")]` + --> tests/ui/view/missing_name.rs:3:10 + | +3 | #[derive(Collection)] + | ^^^^^^^^^^ + | + = note: this error originates in the derive macro `Collection` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/bonsaidb-macros/tests/view.rs b/crates/bonsaidb-macros/tests/view.rs new file mode 100644 index 00000000000..f3c69716595 --- /dev/null +++ b/crates/bonsaidb-macros/tests/view.rs @@ -0,0 +1,16 @@ +use bonsaidb::core::schema::Collection; +use core::fmt::Debug; + +#[test] +fn name_only() { + use bonsaidb::core::schema::View; + + #[derive(Collection, Debug)] + #[collection(name = "name", authority = "authority")] + struct TestCollection; + + #[derive(View, Debug)] + #[view(collection = TestCollection, name = "some strange name äöü")] + #[view(key = ())] + struct TestView; +} From c76a0c6cb3a606569570ce810d93139942f57870 Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Wed, 2 Feb 2022 19:26:35 +0100 Subject: [PATCH 06/12] view derive --- crates/bonsaidb-macros/Cargo.toml | 4 + crates/bonsaidb-macros/src/lib.rs | 142 +++--------------- .../tests/ui/view/invalid_attribute.rs | 6 +- .../tests/ui/view/invalid_attribute.stderr | 8 +- .../tests/ui/view/missing_authority.rs | 7 - .../tests/ui/view/missing_authority.stderr | 7 - .../tests/ui/view/missing_collection.rs | 7 + .../tests/ui/view/missing_collection.stderr | 7 + .../tests/ui/view/missing_key.rs | 7 + .../tests/ui/view/missing_key.stderr | 7 + 10 files changed, 57 insertions(+), 145 deletions(-) delete mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_authority.rs delete mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_authority.stderr create mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_collection.rs create mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_collection.stderr create mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_key.rs create mode 100644 crates/bonsaidb-macros/tests/ui/view/missing_key.stderr diff --git a/crates/bonsaidb-macros/Cargo.toml b/crates/bonsaidb-macros/Cargo.toml index bf9aea15c09..1902b329ec4 100644 --- a/crates/bonsaidb-macros/Cargo.toml +++ b/crates/bonsaidb-macros/Cargo.toml @@ -21,6 +21,10 @@ quote = "1" syn = "1" trybuild = "1.0.54" +# TODO change this to version after release of attribute-derive +[dependencies.attribute-derive] +git = "https://github.com/ModProg/attribute-derive" + [dev-dependencies] compiletest_rs = "0.7" transmog-bincode = "0.1.0-dev.2" diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index e9bfd95ea7e..823da6bd188 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -12,17 +12,13 @@ )] #![cfg_attr(doc, deny(rustdoc::all))] -use proc_macro2::{Spacing, TokenStream}; +use attribute_derive::Attribute; +use proc_macro2::TokenStream; use proc_macro_error::{abort, abort_call_site, proc_macro_error, ResultExt}; use quote::quote; use syn::{ - parse::{Parse, ParseStream}, - parse_macro_input, - punctuated::Punctuated, - spanned::Spanned, - token::Paren, - DeriveInput, Error, Ident, Lit, LitStr, Meta, MetaList, MetaNameValue, NestedMeta, Path, - Result, Type, TypeTuple, + parse_macro_input, punctuated::Punctuated, spanned::Spanned, token::Paren, DeriveInput, Lit, + LitStr, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, TypeTuple, }; /// Derives the `bonsaidb::core::schema::Collection` trait. @@ -37,7 +33,6 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr .. } = parse_macro_input!(input as DeriveInput); - let mut name: Option = None; let mut authority: Option = None; let mut views: Vec = Vec::new(); @@ -153,106 +148,17 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr .into() } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Attribute)] +#[attribute(view)] struct ViewAttribute { - collection: Option, - key: Option, + collection: Type, + key: Type, + #[attribute(default)] name: Option, + #[attribute(default)] value: Option, } -impl ViewAttribute { - pub fn extend_with(&mut self, other: Self) -> Result<()> { - match (&self.collection, other.collection) { - (None, value @ Some(_)) => self.collection = value, - (Some(first), Some(second)) => { - let mut error = - Error::new_spanned(first, "`collection` type is specified multiple times"); - error.combine(Error::new_spanned( - second, - "`collection` type was already specified", - )); - return Err(error); - } - _ => (), - } - match (&self.key, other.key) { - (None, value @ Some(_)) => self.key = value, - (Some(first), Some(second)) => { - let mut error = Error::new_spanned(first, "`key` type is specified multiple times"); - error.combine(Error::new_spanned( - second, - "`key` type was already specified", - )); - return Err(error); - } - _ => (), - } - match (&self.name, other.name) { - (None, value @ Some(_)) => self.name = value, - (Some(first), Some(second)) => { - let mut error = - Error::new_spanned(first, "`name` type is specified multiple times"); - error.combine(Error::new_spanned( - second, - "`name` type was already specified", - )); - return Err(error); - } - _ => (), - } - Ok(()) - } -} - -impl Parse for ViewAttribute { - fn parse(input: ParseStream<'_>) -> Result { - let mut view_attribute = Self::default(); - loop { - let variable = Ident::parse(input)?; - - // Parse `=` - input.step(|cursor| match cursor.punct() { - Some((punct, rest)) - if punct.as_char() == '=' && punct.spacing() == Spacing::Alone => - { - Ok(((), rest)) - } - _ => Err(cursor.error("Expected assignment `=`")), - })?; - - match variable.to_string().as_str() { - "collection" => { - view_attribute.collection = Some(input.parse()?); - } - "key" => { - view_attribute.key = Some(input.parse()?); - } - "name" => { - view_attribute.name = Some(input.parse()?); - } - _ => { - return Err(Error::new( - variable.span(), - "Expected either `collection`, `key` or `name`", - )) - } - } - - if input.is_empty() { - break; - } - - // Parse `,` - input.step(|cursor| match cursor.punct() { - Some((punct, rest)) if punct.as_char() == ',' => Ok(((), rest)), - _ => Err(cursor.error("Expected assignment `=`")), - })?; - } - Ok(view_attribute) - } -} - /// Derives the `bonsaidb::core::schema::View` trait. #[proc_macro_error] /// `#[view(collection(CollectionType), key(KeyType), value(ValueType), name = "by-name", version = 0)]` @@ -265,32 +171,20 @@ pub fn view_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { .. } = parse_macro_input!(input as DeriveInput); - let mut attributes = ViewAttribute::default(); + let ViewAttribute { + collection, + key, + name, + value, + } = ViewAttribute::from_attributes(attrs).unwrap_or_abort(); - for attibute in attrs { - if attibute.path.is_ident("view") { - attributes - .extend_with(attibute.parse_args().unwrap_or_abort()) - .unwrap_or_abort(); - } - } - - let collection = attributes.collection.unwrap_or_else(|| { - abort_call_site!( - r#"You need to specify the collection type via `#[view(collection = CollectionType)]`"# - ) - }); - let key = attributes.key.unwrap_or_else(|| { - abort_call_site!(r#"You need to specify the key type via `#[view(key = KeyType)]`"#) - }); - let value = attributes.value.unwrap_or_else(|| { + let value = value.unwrap_or_else(|| { Type::Tuple(TypeTuple { paren_token: Paren::default(), elems: Punctuated::new(), }) }); - let name = attributes - .name + let name = name .as_ref() .map_or_else(|| ident.to_string(), LitStr::value); diff --git a/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.rs b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.rs index 51ab720c94e..62799c4e05f 100644 --- a/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.rs +++ b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.rs @@ -1,7 +1,7 @@ -use bonsaidb::core::schema::Collection; +use bonsaidb::core::schema::View; -#[derive(Collection)] -#[collection(name = "hi", authority = "hello", "hi")] +#[derive(View)] +#[view(name = "hi", authority = "hello", "hi")] struct Test; fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr index 66f3195eb1d..45e94f10941 100644 --- a/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr +++ b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr @@ -1,5 +1,5 @@ -error: Only `authority="some-authority"`, `name="some-name"`, `views(SomeView, AnotherView)` are supported attributes - --> tests/ui/view/invalid_attribute.rs:4:48 +error: Supported fields are `collection`, `key`, `name` and `value` + --> tests/ui/view/invalid_attribute.rs:4:21 | -4 | #[collection(name = "hi", authority = "hello", "hi")] - | ^^^^ +4 | #[view(name = "hi", authority = "hello", "hi")] + | ^^^^^^^^^ diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_authority.rs b/crates/bonsaidb-macros/tests/ui/view/missing_authority.rs deleted file mode 100644 index c55793618d3..00000000000 --- a/crates/bonsaidb-macros/tests/ui/view/missing_authority.rs +++ /dev/null @@ -1,7 +0,0 @@ -use bonsaidb::core::schema::Collection; - -#[derive(Collection)] -#[collection(name = "hello")] -struct Test; - -fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_authority.stderr b/crates/bonsaidb-macros/tests/ui/view/missing_authority.stderr deleted file mode 100644 index 5493a630caa..00000000000 --- a/crates/bonsaidb-macros/tests/ui/view/missing_authority.stderr +++ /dev/null @@ -1,7 +0,0 @@ -error: You need to specify the collection name via `#[collection(authority="authority")]` - --> tests/ui/view/missing_authority.rs:3:10 - | -3 | #[derive(Collection)] - | ^^^^^^^^^^ - | - = note: this error originates in the derive macro `Collection` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_collection.rs b/crates/bonsaidb-macros/tests/ui/view/missing_collection.rs new file mode 100644 index 00000000000..0e34a02c19c --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/missing_collection.rs @@ -0,0 +1,7 @@ +use bonsaidb::core::schema::View; + +#[derive(View)] +#[view(key = ())] +struct Test; + +fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_collection.stderr b/crates/bonsaidb-macros/tests/ui/view/missing_collection.stderr new file mode 100644 index 00000000000..bc8ef040878 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/missing_collection.stderr @@ -0,0 +1,7 @@ +error: Mandatory `collection` was not specified via the attributes. + --> tests/ui/view/missing_collection.rs:3:10 + | +3 | #[derive(View)] + | ^^^^ + | + = note: this error originates in the derive macro `View` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_key.rs b/crates/bonsaidb-macros/tests/ui/view/missing_key.rs new file mode 100644 index 00000000000..c72744424d0 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/missing_key.rs @@ -0,0 +1,7 @@ +use bonsaidb::core::schema::View; + +#[derive(View)] +#[view(collection = ())] +struct Test; + +fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_key.stderr b/crates/bonsaidb-macros/tests/ui/view/missing_key.stderr new file mode 100644 index 00000000000..4fc74a5fe01 --- /dev/null +++ b/crates/bonsaidb-macros/tests/ui/view/missing_key.stderr @@ -0,0 +1,7 @@ +error: Mandatory `key` was not specified via the attributes. + --> tests/ui/view/missing_key.rs:3:10 + | +3 | #[derive(View)] + | ^^^^ + | + = note: this error originates in the derive macro `View` (in Nightly builds, run with -Z macro-backtrace for more info) From 5140a0fc85fc5562f6db091517c25e32a1f79503 Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Fri, 4 Feb 2022 06:41:21 +0100 Subject: [PATCH 07/12] better parsing and errors with attribute-derive --- crates/bonsaidb-macros/src/lib.rs | 134 ++++++------------ crates/bonsaidb-macros/tests/collection.rs | 6 +- .../tests/ui/collection/invalid_attribute.rs | 4 + .../ui/collection/invalid_attribute.stderr | 8 +- .../ui/collection/missing_authority.stderr | 2 +- .../tests/ui/collection/missing_name.stderr | 2 +- .../tests/ui/view/invalid_attribute.stderr | 2 +- .../tests/ui/view/missing_collection.stderr | 2 +- .../tests/ui/view/missing_key.stderr | 2 +- .../tests/ui/view/missing_name.stderr | 2 +- 10 files changed, 65 insertions(+), 99 deletions(-) diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index 823da6bd188..893b843f33c 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -14,16 +14,37 @@ use attribute_derive::Attribute; use proc_macro2::TokenStream; -use proc_macro_error::{abort, abort_call_site, proc_macro_error, ResultExt}; +use proc_macro_error::{proc_macro_error, ResultExt}; use quote::quote; use syn::{ - parse_macro_input, punctuated::Punctuated, spanned::Spanned, token::Paren, DeriveInput, Lit, - LitStr, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, TypeTuple, + parse_macro_input, punctuated::Punctuated, token::Paren, DeriveInput, LitStr, Path, Type, + TypeTuple, }; +#[derive(Attribute)] +#[attribute(ident = "collection")] +#[attribute( + invalid_field = r#"Only `authority = "some-authority"`, `name = "some-name"`, `views = [SomeView, AnotherView]`, `serialization = Serialization` are supported attributes"# +)] +struct CollectionAttribute { + #[attribute( + missing = r#"You need to specify the collection authority via `#[collection(authority = "authority")]`"# + )] + authority: String, + #[attribute( + missing = r#"You need to specify the collection name via `#[collection(name = "name")]`"# + )] + name: String, + #[attribute(default)] + #[attribute(expected = r#"Specify the `views` like so: `view = [SomeView, AnotherView]`"#)] + views: Vec, + #[attribute(expected = r#"Specify the `serialization` like so: `serialization = Format` or `serialization = None` to disable deriving it"#)] + serialization: Option, +} + /// Derives the `bonsaidb::core::schema::Collection` trait. #[proc_macro_error] -/// `#[collection(authority = "Authority", name = "Name", views(a, b, c))]` +/// `#[collection(authority = "Authority", name = "Name", views = [a, b, c])]` #[proc_macro_derive(Collection, attributes(collection))] pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let DeriveInput { @@ -33,86 +54,12 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr .. } = parse_macro_input!(input as DeriveInput); - let mut name: Option = None; - let mut authority: Option = None; - let mut views: Vec = Vec::new(); - let mut serialization: Option = None; - - for attibute in attrs { - if attibute.path.is_ident("collection") { - if let Ok(Meta::List(MetaList { nested, .. })) = attibute.parse_meta() { - for item in nested { - let span = item.span(); - match item { - NestedMeta::Meta(Meta::NameValue(MetaNameValue { - path, - lit: Lit::Str(value), - .. - })) if path.is_ident("name") => name = Some(value.value()), - NestedMeta::Meta(Meta::NameValue(MetaNameValue { - path, - lit: Lit::Str(value), - .. - })) if path.is_ident("authority") => authority = Some(value.value()), - NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) - if path.is_ident("serialization") => - { - match nested.len() { - 0 => abort!( - span, - r#"You need to pass either a format type or `None` to `serialization`: `serialization(Format)`"#, - ), - 2.. => abort!( - span, - r#"You can only specify a single format with `serialization` like so: `serialization(Format)`"#, - ), - _ => (), - } - serialization = nested - .into_iter() - .map(|meta| match meta { - NestedMeta::Meta(Meta::Path(path)) => path, - meta => abort!( - meta.span(), - r#"`{}` is not supported here, call `serialization` like so: `serialization(Format)`"# - ), - }).next(); - } - NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) - if path.is_ident("views") => - { - views = nested - .into_iter() - .map(|meta| match meta { - NestedMeta::Meta(Meta::Path(path)) => path, - meta => abort!( - meta.span(), - r#"`{}` is not supported here, call `views` like so: `views(SomeView, AnotherView)`"# - ), - }) - .collect(); - } - item => abort!( - item.span(), - r#"Only `authority="some-authority"`, `name="some-name"`, `views(SomeView, AnotherView)` are supported attributes"# - ), - } - } - } - } - } - - let authority = authority.unwrap_or_else(|| { - abort_call_site!( - r#"You need to specify the collection name via `#[collection(authority="authority")]`"# - ) - }); - - let name = name.unwrap_or_else(|| { - abort_call_site!( - r#"You need to specify the collection authority via `#[collection(name="name")]`"# - ) - }); + let CollectionAttribute { + authority, + name, + views, + serialization, + } = CollectionAttribute::from_attributes(attrs).unwrap_or_abort(); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); @@ -148,20 +95,29 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr .into() } -#[derive(Debug, Clone, Attribute)] -#[attribute(view)] +#[derive(Attribute)] +#[attribute(ident = "view")] +#[attribute( + invalid_field = r#"Only `collection = CollectionType`, `key = KeyType`, `name = "by-name"`, `value = ValueType` are supported attributes"# +)] struct ViewAttribute { + #[attribute( + missing = r#"You need to specify the collection type via `#[view(collection = CollectionType)]`"# + )] + #[attribute(expected = r#"Specify the collection type like so: `collection = CollectionType`"#)] collection: Type, + #[attribute(missing = r#"You need to specify the key type via `#[view(key = KeyType)]`"#)] + #[attribute(expected = r#"Specify the key type like so: `key = KeyType`"#)] key: Type, - #[attribute(default)] name: Option, - #[attribute(default)] + #[attribute(expected = r#"Specify the value type like so: `value = ValueType`"#)] value: Option, } /// Derives the `bonsaidb::core::schema::View` trait. #[proc_macro_error] -/// `#[view(collection(CollectionType), key(KeyType), value(ValueType), name = "by-name", version = 0)]` +/// `#[view(collection=CollectionType, key=KeyType, value=ValueType, name = "by-name")]` +/// `name` and `value` are optional #[proc_macro_derive(View, attributes(view))] pub fn view_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let DeriveInput { diff --git a/crates/bonsaidb-macros/tests/collection.rs b/crates/bonsaidb-macros/tests/collection.rs index 3dbb0941d7d..040c3cad9b8 100644 --- a/crates/bonsaidb-macros/tests/collection.rs +++ b/crates/bonsaidb-macros/tests/collection.rs @@ -21,7 +21,7 @@ fn views() { use serde::{Deserialize, Serialize}; #[derive(Collection, Debug, Serialize, Deserialize)] - #[collection(name = "Name", authority = "Authority", views(ShapesByNumberOfSides))] + #[collection(name = "Name", authority = "Authority", views = [ShapesByNumberOfSides])] struct Shape { pub sides: u32, } @@ -62,7 +62,7 @@ fn serialization() { #[collection( name = "Name", authority = "Authority", - serialization(transmog_bincode::Bincode) + serialization = transmog_bincode::Bincode )] struct Test; @@ -80,7 +80,7 @@ fn serialization_none() { use serde::{Deserialize, Serialize}; #[derive(Collection, Debug, Deserialize, Serialize)] - #[collection(name = "Name", authority = "Authority", serialization(None))] + #[collection(name = "Name", authority = "Authority", serialization = None)] struct Test; impl DefaultSerialization for Test {} diff --git a/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.rs b/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.rs index 51ab720c94e..7b845c23af3 100644 --- a/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.rs +++ b/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.rs @@ -4,4 +4,8 @@ use bonsaidb::core::schema::Collection; #[collection(name = "hi", authority = "hello", "hi")] struct Test; +#[derive(Collection)] +#[collection(name = "hi", authority = "hello", field = 200)] +struct Test2; + fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.stderr b/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.stderr index aa47df43536..0f74d8a9a3e 100644 --- a/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.stderr +++ b/crates/bonsaidb-macros/tests/ui/collection/invalid_attribute.stderr @@ -1,5 +1,11 @@ -error: Only `authority="some-authority"`, `name="some-name"`, `views(SomeView, AnotherView)` are supported attributes +error: expected identifier --> tests/ui/collection/invalid_attribute.rs:4:48 | 4 | #[collection(name = "hi", authority = "hello", "hi")] | ^^^^ + +error: Only `authority = \"some-authority\"`, `name = \"some-name\"`, `views = [SomeView, AnotherView]`, `serialization = Serialization` are supported attributes + --> tests/ui/collection/invalid_attribute.rs:8:48 + | +8 | #[collection(name = "hi", authority = "hello", field = 200)] + | ^^^^^ diff --git a/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr b/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr index 14543cb7165..c4059dea2a4 100644 --- a/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr +++ b/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr @@ -1,4 +1,4 @@ -error: You need to specify the collection name via `#[collection(authority="authority")]` +error: You need to specify the collection authority via `#[collection(authority = \"authority\")]` --> tests/ui/collection/missing_authority.rs:3:10 | 3 | #[derive(Collection)] diff --git a/crates/bonsaidb-macros/tests/ui/collection/missing_name.stderr b/crates/bonsaidb-macros/tests/ui/collection/missing_name.stderr index a72e0ee64fd..4bdc2d3d53d 100644 --- a/crates/bonsaidb-macros/tests/ui/collection/missing_name.stderr +++ b/crates/bonsaidb-macros/tests/ui/collection/missing_name.stderr @@ -1,4 +1,4 @@ -error: You need to specify the collection authority via `#[collection(name="name")]` +error: You need to specify the collection name via `#[collection(name = \"name\")]` --> tests/ui/collection/missing_name.rs:3:10 | 3 | #[derive(Collection)] diff --git a/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr index 45e94f10941..5c9ff145e44 100644 --- a/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr +++ b/crates/bonsaidb-macros/tests/ui/view/invalid_attribute.stderr @@ -1,4 +1,4 @@ -error: Supported fields are `collection`, `key`, `name` and `value` +error: Only `collection = CollectionType`, `key = KeyType`, `name = \"by-name\"`, `value = ValueType` are supported attributes --> tests/ui/view/invalid_attribute.rs:4:21 | 4 | #[view(name = "hi", authority = "hello", "hi")] diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_collection.stderr b/crates/bonsaidb-macros/tests/ui/view/missing_collection.stderr index bc8ef040878..9da167e34bb 100644 --- a/crates/bonsaidb-macros/tests/ui/view/missing_collection.stderr +++ b/crates/bonsaidb-macros/tests/ui/view/missing_collection.stderr @@ -1,4 +1,4 @@ -error: Mandatory `collection` was not specified via the attributes. +error: You need to specify the collection type via `#[view(collection = CollectionType)]` --> tests/ui/view/missing_collection.rs:3:10 | 3 | #[derive(View)] diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_key.stderr b/crates/bonsaidb-macros/tests/ui/view/missing_key.stderr index 4fc74a5fe01..fdae0981b52 100644 --- a/crates/bonsaidb-macros/tests/ui/view/missing_key.stderr +++ b/crates/bonsaidb-macros/tests/ui/view/missing_key.stderr @@ -1,4 +1,4 @@ -error: Mandatory `key` was not specified via the attributes. +error: You need to specify the key type via `#[view(key = KeyType)]` --> tests/ui/view/missing_key.rs:3:10 | 3 | #[derive(View)] diff --git a/crates/bonsaidb-macros/tests/ui/view/missing_name.stderr b/crates/bonsaidb-macros/tests/ui/view/missing_name.stderr index 2dfa0934e95..5f5af847c00 100644 --- a/crates/bonsaidb-macros/tests/ui/view/missing_name.stderr +++ b/crates/bonsaidb-macros/tests/ui/view/missing_name.stderr @@ -1,4 +1,4 @@ -error: You need to specify the collection authority via `#[collection(name="name")]` +error: You need to specify the collection name via `#[collection(name = \"name\")]` --> tests/ui/view/missing_name.rs:3:10 | 3 | #[derive(Collection)] From 91628fec11c736545ba6608587d75f2520a4f4f3 Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Fri, 4 Feb 2022 06:43:56 +0100 Subject: [PATCH 08/12] test view for collection --- crates/bonsaidb-macros/tests/collection.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/bonsaidb-macros/tests/collection.rs b/crates/bonsaidb-macros/tests/collection.rs index 040c3cad9b8..5cc0b6cde68 100644 --- a/crates/bonsaidb-macros/tests/collection.rs +++ b/crates/bonsaidb-macros/tests/collection.rs @@ -1,5 +1,7 @@ use core::fmt::Debug; +use bonsaidb::core::schema::Schematic; + #[test] fn name_only() { use bonsaidb::core::schema::Collection; @@ -26,7 +28,8 @@ fn views() { pub sides: u32, } - // TODO somehow test views + let schematic = Schematic::from_schema::().unwrap(); + assert!(schematic.view::().is_some()); #[derive(Debug, Clone)] struct ShapesByNumberOfSides; From 3abae7d8a9ea2260ced4aa591ec5828d3038e85a Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Sun, 6 Feb 2022 00:21:00 +0100 Subject: [PATCH 09/12] get the correct path --- crates/bonsaidb-client/Cargo.toml | 1 + crates/bonsaidb-core/Cargo.toml | 4 ++ crates/bonsaidb-local/Cargo.toml | 2 +- crates/bonsaidb-macros/Cargo.toml | 7 +++ crates/bonsaidb-macros/src/lib.rs | 71 +++++++++++++++++----- crates/bonsaidb-macros/tests/collection.rs | 7 +-- crates/bonsaidb-server/Cargo.toml | 1 + crates/bonsaidb/Cargo.toml | 10 +-- 8 files changed, 79 insertions(+), 24 deletions(-) diff --git a/crates/bonsaidb-client/Cargo.toml b/crates/bonsaidb-client/Cargo.toml index 7f044574d9e..10ccaedf893 100644 --- a/crates/bonsaidb-client/Cargo.toml +++ b/crates/bonsaidb-client/Cargo.toml @@ -23,6 +23,7 @@ password-hashing = ["bonsaidb-core/password-hashing"] [dependencies] bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0", default-features = false, features = [ "networking", + "included-from-client" ] } bonsaidb-utils = { path = "../bonsaidb-utils", version = "0.1.0" } thiserror = "1" diff --git a/crates/bonsaidb-core/Cargo.toml b/crates/bonsaidb-core/Cargo.toml index 1f5c164333e..0346e214e0e 100644 --- a/crates/bonsaidb-core/Cargo.toml +++ b/crates/bonsaidb-core/Cargo.toml @@ -21,6 +21,10 @@ instrument = ["pot/tracing"] multiuser = ["zeroize"] encryption = [] password-hashing = ["multiuser"] +included-from-omnibus = ["bonsaidb-macros/omnibus-path"] +included-from-server = ["bonsaidb-macros/server-path"] +included-from-local = ["bonsaidb-macros/local-path"] +included-from-client = ["bonsaidb-macros/client-path"] [dependencies] bonsaidb-macros = { path = "../bonsaidb-macros", version = "0.1.0" } diff --git a/crates/bonsaidb-local/Cargo.toml b/crates/bonsaidb-local/Cargo.toml index 5775b1447aa..5c2de05e6ac 100644 --- a/crates/bonsaidb-local/Cargo.toml +++ b/crates/bonsaidb-local/Cargo.toml @@ -39,7 +39,7 @@ included-from-omnibus = [] [dependencies] async-trait = "0.1" -bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0" } +bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0", features = ["included-from-local"] } bonsaidb-utils = { path = "../bonsaidb-utils", version = "0.1.0" } nebari = { version = "0.2" } thiserror = "1" diff --git a/crates/bonsaidb-macros/Cargo.toml b/crates/bonsaidb-macros/Cargo.toml index 1902b329ec4..a91682123a1 100644 --- a/crates/bonsaidb-macros/Cargo.toml +++ b/crates/bonsaidb-macros/Cargo.toml @@ -20,6 +20,7 @@ proc-macro2 = "1.0.36" quote = "1" syn = "1" trybuild = "1.0.54" +proc-macro-crate = "1.1.0" # TODO change this to version after release of attribute-derive [dependencies.attribute-derive] @@ -35,3 +36,9 @@ path = "../bonsaidb/" [dev-dependencies.serde] version = "1.0.133" features = ["derive"] + +[features] +omnibus-path = [] +server-path = [] +local-path = [] +client-path = [] diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index 893b843f33c..5dc5a18c2d9 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -13,14 +13,43 @@ #![cfg_attr(doc, deny(rustdoc::all))] use attribute_derive::Attribute; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; +use proc_macro_crate::{crate_name, FoundCrate}; use proc_macro_error::{proc_macro_error, ResultExt}; use quote::quote; use syn::{ - parse_macro_input, punctuated::Punctuated, token::Paren, DeriveInput, LitStr, Path, Type, - TypeTuple, + parse_macro_input, parse_quote, punctuated::Punctuated, token::Paren, DeriveInput, Ident, + LitStr, Path, Type, TypeTuple, }; +fn core_path() -> Path { + match crate_name("bonsaidb") + .or_else(|_| crate_name("bonsaidb_server")) + .or_else(|_| crate_name("bonsaidb_local")) + .or_else(|_| crate_name("bonsaidb_client")) + { + Ok(FoundCrate::Name(name)) => { + let ident = Ident::new(&name, Span::call_site()); + parse_quote!(::#ident::core) + } + Ok(FoundCrate::Itself) => parse_quote!(crate), + Err(_) => match crate_name("bonsaidb_core") { + Ok(FoundCrate::Name(name)) => { + let ident = Ident::new(&name, Span::call_site()); + parse_quote!(::#ident::core) + } + Ok(FoundCrate::Itself) => parse_quote!(crate), + Err(_) => match () { + () if cfg!(feature = "omnibus-path") => parse_quote!(::bonsaidb::core), + () if cfg!(feature = "server-path") => parse_quote!(::bonsaidb_server::core), + () if cfg!(feature = "local-path") => parse_quote!(::bonsaidb_local::core), + () if cfg!(feature = "client-path") => parse_quote!(::bonsaidb_client::core), + _ => parse_quote!(::bonsaidb_core), + }, + }, + } +} + #[derive(Attribute)] #[attribute(ident = "collection")] #[attribute( @@ -38,8 +67,12 @@ struct CollectionAttribute { #[attribute(default)] #[attribute(expected = r#"Specify the `views` like so: `view = [SomeView, AnotherView]`"#)] views: Vec, - #[attribute(expected = r#"Specify the `serialization` like so: `serialization = Format` or `serialization = None` to disable deriving it"#)] + #[attribute( + expected = r#"Specify the `serialization` like so: `serialization = Format` or `serialization = None` to disable deriving it"# + )] serialization: Option, + #[attribute(expected = r#"Specify the the path to `core` like so: `core = bosaidb::core`"#)] + core: Option, } /// Derives the `bonsaidb::core::schema::Collection` trait. @@ -59,14 +92,17 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr name, views, serialization, + core, } = CollectionAttribute::from_attributes(attrs).unwrap_or_abort(); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let core = core.unwrap_or_else(core_path); + let serialization = match serialization { Some(serialization) if serialization.is_ident("None") => TokenStream::new(), Some(serialization) => quote! { - impl #impl_generics ::bonsaidb::core::schema::SerializedCollection for #ident #ty_generics #where_clause { + impl #impl_generics #core::schema::SerializedCollection for #ident #ty_generics #where_clause { type Contents = #ident #ty_generics; type Format = #serialization; @@ -76,16 +112,16 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr } }, None => quote! { - impl #impl_generics ::bonsaidb::core::schema::DefaultSerialization for #ident #ty_generics #where_clause {} + impl #impl_generics #core::schema::DefaultSerialization for #ident #ty_generics #where_clause {} }, }; quote! { - impl #impl_generics ::bonsaidb::core::schema::Collection for #ident #ty_generics #where_clause { - fn collection_name() -> ::bonsaidb::core::schema::CollectionName { - ::bonsaidb::core::schema::CollectionName::new(#authority, #name) + impl #impl_generics #core::schema::Collection for #ident #ty_generics #where_clause { + fn collection_name() -> #core::schema::CollectionName { + #core::schema::CollectionName::new(#authority, #name) } - fn define_views(schema: &mut ::bonsaidb::core::schema::Schematic) -> ::core::result::Result<(), ::bonsaidb::core::Error>{ + fn define_views(schema: &mut #core::schema::Schematic) -> ::core::result::Result<(), #core::Error>{ #( schema.define_view(#views)?; )* ::core::result::Result::Ok(()) } @@ -104,7 +140,9 @@ struct ViewAttribute { #[attribute( missing = r#"You need to specify the collection type via `#[view(collection = CollectionType)]`"# )] - #[attribute(expected = r#"Specify the collection type like so: `collection = CollectionType`"#)] + #[attribute( + expected = r#"Specify the collection type like so: `collection = CollectionType`"# + )] collection: Type, #[attribute(missing = r#"You need to specify the key type via `#[view(key = KeyType)]`"#)] #[attribute(expected = r#"Specify the key type like so: `key = KeyType`"#)] @@ -112,6 +150,8 @@ struct ViewAttribute { name: Option, #[attribute(expected = r#"Specify the value type like so: `value = ValueType`"#)] value: Option, + #[attribute(expected = r#"Specify the the path to `core` like so: `core = bosaidb::core`"#)] + core: Option, } /// Derives the `bonsaidb::core::schema::View` trait. @@ -132,8 +172,11 @@ pub fn view_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { key, name, value, + core } = ViewAttribute::from_attributes(attrs).unwrap_or_abort(); + let core = core.unwrap_or_else(core_path); + let value = value.unwrap_or_else(|| { Type::Tuple(TypeTuple { paren_token: Paren::default(), @@ -147,13 +190,13 @@ pub fn view_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); quote! { - impl #impl_generics ::bonsaidb::core::schema::View for #ident #ty_generics #where_clause { + impl #impl_generics #core::schema::View for #ident #ty_generics #where_clause { type Collection = #collection; type Key = #key; type Value = #value; - fn name(&self) -> ::bonsaidb::core::schema::Name { - ::bonsaidb::core::schema::Name::new(#name) + fn name(&self) -> #core::schema::Name { + #core::schema::Name::new(#name) } } } diff --git a/crates/bonsaidb-macros/tests/collection.rs b/crates/bonsaidb-macros/tests/collection.rs index 5cc0b6cde68..b88ecfe15d9 100644 --- a/crates/bonsaidb-macros/tests/collection.rs +++ b/crates/bonsaidb-macros/tests/collection.rs @@ -1,12 +1,12 @@ use core::fmt::Debug; -use bonsaidb::core::schema::Schematic; +use bonsaidb::core::{schema::Schematic, document::CollectionDocument}; #[test] fn name_only() { use bonsaidb::core::schema::Collection; #[derive(Collection, Debug)] - #[collection(name = "Name", authority = "Authority")] + #[collection(name = "Name", authority = "Authority", core = ::bonsaidb::core)] struct Test(T); assert_eq!( @@ -17,8 +17,7 @@ fn name_only() { #[test] fn views() { use bonsaidb::core::schema::{ - Collection, CollectionDocument, CollectionViewSchema, DefaultViewSerialization, Name, View, - ViewMapResult, + Collection, CollectionViewSchema, DefaultViewSerialization, Name, View, ViewMapResult, }; use serde::{Deserialize, Serialize}; diff --git a/crates/bonsaidb-server/Cargo.toml b/crates/bonsaidb-server/Cargo.toml index 75332223549..fa661cca271 100644 --- a/crates/bonsaidb-server/Cargo.toml +++ b/crates/bonsaidb-server/Cargo.toml @@ -38,6 +38,7 @@ bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0", default-features "networking", "actionable-traits", "multiuser", + "included-from-server" ] } bonsaidb-local = { path = "../bonsaidb-local", version = "0.1.0", default-features = false, features = [ "internal-apis", diff --git a/crates/bonsaidb/Cargo.toml b/crates/bonsaidb/Cargo.toml index 1725faa36c1..3fa53088a4b 100644 --- a/crates/bonsaidb/Cargo.toml +++ b/crates/bonsaidb/Cargo.toml @@ -103,11 +103,11 @@ client-password-hashing = [ ] [dependencies] -bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0", default-features = false } -bonsaidb-local = { path = "../bonsaidb-local", version = "0.1.0", default-features = false, optional = true } -bonsaidb-client = { path = "../bonsaidb-client", version = "0.1.0", default-features = false, optional = true } -bonsaidb-server = { path = "../bonsaidb-server", version = "0.1.0", default-features = false, optional = true } -bonsaidb-keystorage-s3 = { path = "../bonsaidb-keystorage-s3", version = "0.1.0", default-features = false, optional = true } +bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0-dev.4", default-features = false, features=["included-from-omnibus"] } +bonsaidb-local = { path = "../bonsaidb-local", version = "0.1.0-dev.4", default-features = false, optional = true } +bonsaidb-client = { path = "../bonsaidb-client", version = "0.1.0-dev.4", default-features = false, optional = true } +bonsaidb-server = { path = "../bonsaidb-server", version = "0.1.0-dev.4", default-features = false, optional = true } +bonsaidb-keystorage-s3 = { path = "../bonsaidb-keystorage-s3", version = "0.1.0-dev.4", default-features = false, optional = true } tokio = { version = "1", features = ["full"], optional = true } clap = { version = "3", optional = true, features = ["derive"] } From 7cb630e4011c89b42fcbcec3f90e01bdddbc9109 Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Sun, 6 Feb 2022 14:38:29 +0100 Subject: [PATCH 10/12] Optional authority --- crates/bonsaidb-macros/src/lib.rs | 14 ++++++++------ crates/bonsaidb-macros/tests/collection.rs | 16 ++++++++++++++-- .../tests/ui/collection/missing_authority.rs | 7 ------- .../tests/ui/collection/missing_authority.stderr | 7 ------- 4 files changed, 22 insertions(+), 22 deletions(-) delete mode 100644 crates/bonsaidb-macros/tests/ui/collection/missing_authority.rs delete mode 100644 crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr diff --git a/crates/bonsaidb-macros/src/lib.rs b/crates/bonsaidb-macros/src/lib.rs index 5dc5a18c2d9..0d2154506c9 100644 --- a/crates/bonsaidb-macros/src/lib.rs +++ b/crates/bonsaidb-macros/src/lib.rs @@ -56,10 +56,7 @@ fn core_path() -> Path { invalid_field = r#"Only `authority = "some-authority"`, `name = "some-name"`, `views = [SomeView, AnotherView]`, `serialization = Serialization` are supported attributes"# )] struct CollectionAttribute { - #[attribute( - missing = r#"You need to specify the collection authority via `#[collection(authority = "authority")]`"# - )] - authority: String, + authority: Option, #[attribute( missing = r#"You need to specify the collection name via `#[collection(name = "name")]`"# )] @@ -116,10 +113,15 @@ pub fn collection_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStr }, }; + let name = authority.map_or_else( + || quote!(#core::schema::CollectionName::private(#name)), + |authority| quote!(#core::schema::CollectionName::new(#authority, #name)), + ); + quote! { impl #impl_generics #core::schema::Collection for #ident #ty_generics #where_clause { fn collection_name() -> #core::schema::CollectionName { - #core::schema::CollectionName::new(#authority, #name) + #name } fn define_views(schema: &mut #core::schema::Schematic) -> ::core::result::Result<(), #core::Error>{ #( schema.define_view(#views)?; )* @@ -172,7 +174,7 @@ pub fn view_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { key, name, value, - core + core, } = ViewAttribute::from_attributes(attrs).unwrap_or_abort(); let core = core.unwrap_or_else(core_path); diff --git a/crates/bonsaidb-macros/tests/collection.rs b/crates/bonsaidb-macros/tests/collection.rs index b88ecfe15d9..a006ec6f776 100644 --- a/crates/bonsaidb-macros/tests/collection.rs +++ b/crates/bonsaidb-macros/tests/collection.rs @@ -1,12 +1,24 @@ use core::fmt::Debug; -use bonsaidb::core::{schema::Schematic, document::CollectionDocument}; +use bonsaidb::core::{document::CollectionDocument, schema::Schematic}; #[test] fn name_only() { use bonsaidb::core::schema::Collection; #[derive(Collection, Debug)] - #[collection(name = "Name", authority = "Authority", core = ::bonsaidb::core)] + #[collection(name = "Name", core = ::bonsaidb::core)] + struct Test(T); + + assert_eq!( + Test::::collection_name(), + bonsaidb::core::schema::CollectionName::private("Name") + ); +} +#[test] +fn name_and_authority() { + use bonsaidb::core::schema::Collection; + #[derive(Collection, Debug)] + #[collection(name = "Name", authority = "Authority")] struct Test(T); assert_eq!( diff --git a/crates/bonsaidb-macros/tests/ui/collection/missing_authority.rs b/crates/bonsaidb-macros/tests/ui/collection/missing_authority.rs deleted file mode 100644 index c55793618d3..00000000000 --- a/crates/bonsaidb-macros/tests/ui/collection/missing_authority.rs +++ /dev/null @@ -1,7 +0,0 @@ -use bonsaidb::core::schema::Collection; - -#[derive(Collection)] -#[collection(name = "hello")] -struct Test; - -fn main() {} diff --git a/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr b/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr deleted file mode 100644 index c4059dea2a4..00000000000 --- a/crates/bonsaidb-macros/tests/ui/collection/missing_authority.stderr +++ /dev/null @@ -1,7 +0,0 @@ -error: You need to specify the collection authority via `#[collection(authority = \"authority\")]` - --> tests/ui/collection/missing_authority.rs:3:10 - | -3 | #[derive(Collection)] - | ^^^^^^^^^^ - | - = note: this error originates in the derive macro `Collection` (in Nightly builds, run with -Z macro-backtrace for more info) From 05046fad6c2803b72335d54f08bcab854e9c792d Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Sun, 6 Feb 2022 17:56:26 +0100 Subject: [PATCH 11/12] use released version --- crates/bonsaidb-macros/Cargo.toml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/bonsaidb-macros/Cargo.toml b/crates/bonsaidb-macros/Cargo.toml index a91682123a1..e957dace14d 100644 --- a/crates/bonsaidb-macros/Cargo.toml +++ b/crates/bonsaidb-macros/Cargo.toml @@ -15,16 +15,13 @@ homepage = "https://bonsaidb.io/" proc-macro = true [dependencies] +attribute-derive = "0.1.0" +proc-macro-crate = "1.1.0" proc-macro-error = "1" proc-macro2 = "1.0.36" quote = "1" syn = "1" trybuild = "1.0.54" -proc-macro-crate = "1.1.0" - -# TODO change this to version after release of attribute-derive -[dependencies.attribute-derive] -git = "https://github.com/ModProg/attribute-derive" [dev-dependencies] compiletest_rs = "0.7" From 1afac850ffddf86e59be1afe785d87b1bdd9918f Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Sun, 6 Feb 2022 18:25:36 +0100 Subject: [PATCH 12/12] Fix versions Co-authored-by: Jonathan Johnson --- crates/bonsaidb/Cargo.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bonsaidb/Cargo.toml b/crates/bonsaidb/Cargo.toml index 3fa53088a4b..ad1e184e3c4 100644 --- a/crates/bonsaidb/Cargo.toml +++ b/crates/bonsaidb/Cargo.toml @@ -103,11 +103,11 @@ client-password-hashing = [ ] [dependencies] -bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0-dev.4", default-features = false, features=["included-from-omnibus"] } -bonsaidb-local = { path = "../bonsaidb-local", version = "0.1.0-dev.4", default-features = false, optional = true } -bonsaidb-client = { path = "../bonsaidb-client", version = "0.1.0-dev.4", default-features = false, optional = true } -bonsaidb-server = { path = "../bonsaidb-server", version = "0.1.0-dev.4", default-features = false, optional = true } -bonsaidb-keystorage-s3 = { path = "../bonsaidb-keystorage-s3", version = "0.1.0-dev.4", default-features = false, optional = true } +bonsaidb-core = { path = "../bonsaidb-core", version = "0.1.0", default-features = false, features=["included-from-omnibus"] } +bonsaidb-local = { path = "../bonsaidb-local", version = "0.1.0", default-features = false, optional = true } +bonsaidb-client = { path = "../bonsaidb-client", version = "0.1.0", default-features = false, optional = true } +bonsaidb-server = { path = "../bonsaidb-server", version = "0.1.0", default-features = false, optional = true } +bonsaidb-keystorage-s3 = { path = "../bonsaidb-keystorage-s3", version = "0.1.0", default-features = false, optional = true } tokio = { version = "1", features = ["full"], optional = true } clap = { version = "3", optional = true, features = ["derive"] }