diff --git a/contrib/db_pools/codegen/Cargo.toml b/contrib/db_pools/codegen/Cargo.toml index a9aa7315..770388c7 100644 --- a/contrib/db_pools/codegen/Cargo.toml +++ b/contrib/db_pools/codegen/Cargo.toml @@ -19,3 +19,5 @@ quote = "1" [dev-dependencies] rocket = { path = "../../../core/lib", default-features = false } rocket_db_pools = { path = "../lib", features = ["deadpool_postgres"] } +trybuild = "1.0" +version_check = "0.9" diff --git a/contrib/db_pools/codegen/src/database.rs b/contrib/db_pools/codegen/src/database.rs index 52e5dbf6..837aa6c8 100644 --- a/contrib/db_pools/codegen/src/database.rs +++ b/contrib/db_pools/codegen/src/database.rs @@ -21,19 +21,23 @@ pub fn derive_database(input: TokenStream) -> TokenStream { if s.fields.len() == 1 { Ok(()) } else { - Err(s.fields.span().error(ONE_UNNAMED_FIELD)) + Err(s.span().error(ONE_UNNAMED_FIELD)) } }) ) .outer_mapper(MapperBuild::new() .struct_map(|_, s| { - let decorated_type = &s.ident; let pool_type = match &s.fields { syn::Fields::Unnamed(f) => &f.unnamed[0].ty, _ => unreachable!("Support::TupleStruct"), }; - quote_spanned! { s.span() => + let decorated_type = &s.ident; + let db_ty = quote_spanned!(decorated_type.span() => + <#decorated_type as rocket_db_pools::Database> + ); + + quote_spanned! { decorated_type.span() => impl From<#pool_type> for #decorated_type { fn from(pool: #pool_type) -> Self { Self(pool) @@ -61,7 +65,7 @@ pub fn derive_database(input: TokenStream) -> TokenStream { async fn from_request( req: &'r rocket::request::Request<'_> ) -> rocket::request::Outcome { - match #decorated_type::fetch(req.rocket()) { + match #db_ty::fetch(req.rocket()) { Some(db) => rocket::outcome::Outcome::Success(db), None => rocket::outcome::Outcome::Failure(( rocket::http::Status::InternalServerError, ())) @@ -71,7 +75,7 @@ pub fn derive_database(input: TokenStream) -> TokenStream { impl rocket::Sentinel for &#decorated_type { fn abort(rocket: &rocket::Rocket) -> bool { - #decorated_type::fetch(rocket).is_none() + #db_ty::fetch(rocket).is_none() } } } @@ -91,7 +95,7 @@ pub fn derive_database(input: TokenStream) -> TokenStream { _ => unreachable!("Support::TupleStruct"), }; - Ok(quote_spanned! { s.span() => + Ok(quote_spanned! { pool_type.span() => type Pool = #pool_type; const NAME: &'static str = #db_name; diff --git a/contrib/db_pools/codegen/tests/ui-fail-nightly/database-syntax.rs b/contrib/db_pools/codegen/tests/ui-fail-nightly/database-syntax.rs new file mode 120000 index 00000000..717e99bd --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail-nightly/database-syntax.rs @@ -0,0 +1 @@ +../ui-fail/database-syntax.rs \ No newline at end of file diff --git a/contrib/db_pools/codegen/tests/ui-fail-nightly/database-syntax.stderr b/contrib/db_pools/codegen/tests/ui-fail-nightly/database-syntax.stderr new file mode 100644 index 00000000..96b79e34 --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail-nightly/database-syntax.stderr @@ -0,0 +1,109 @@ +error: invalid value: expected string literal + --> $DIR/database-syntax.rs:4:12 + | +4 | #[database(123)] + | ^^^ + | +note: error occurred while deriving `Database` + --> $DIR/database-syntax.rs:3:10 + | +3 | #[derive(Database)] + | ^^^^^^^^ + = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected key/value `key = value` + --> $DIR/database-syntax.rs:8:25 + | +8 | #[database("some-name", "another")] + | ^^^^^^^^^ + | +note: error occurred while deriving `Database` + --> $DIR/database-syntax.rs:7:10 + | +7 | #[derive(Database)] + | ^^^^^^^^ + = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected attribute parameter: `name` + --> $DIR/database-syntax.rs:12:25 + | +12 | #[database("some-name", name = "another")] + | ^^^^^^^^^^^^^^^^ + | +note: error occurred while deriving `Database` + --> $DIR/database-syntax.rs:11:10 + | +11 | #[derive(Database)] + | ^^^^^^^^ + = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: enums are not supported + --> $DIR/database-syntax.rs:16:1 + | +16 | / #[database("foo")] +17 | | enum D { } + | |___________^ + | +note: error occurred while deriving `Database` + --> $DIR/database-syntax.rs:15:10 + | +15 | #[derive(Database)] + | ^^^^^^^^ + = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: missing `#[database("name")]` attribute + --> $DIR/database-syntax.rs:20:1 + | +20 | struct E(deadpool_postgres::Pool); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: error occurred while deriving `Database` + --> $DIR/database-syntax.rs:19:10 + | +19 | #[derive(Database)] + | ^^^^^^^^ + = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: struct must have exactly one unnamed field + --> $DIR/database-syntax.rs:23:1 + | +23 | / #[database("foo")] +24 | | struct F; + | |_________^ + | +note: error occurred while deriving `Database` + --> $DIR/database-syntax.rs:22:10 + | +22 | #[derive(Database)] + | ^^^^^^^^ + = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: struct must have exactly one unnamed field + --> $DIR/database-syntax.rs:27:1 + | +27 | / #[database("foo")] +28 | | struct G(deadpool_postgres::Pool, deadpool_postgres::Pool); + | |___________________________________________________________^ + | +note: error occurred while deriving `Database` + --> $DIR/database-syntax.rs:26:10 + | +26 | #[derive(Database)] + | ^^^^^^^^ + = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: named structs are not supported + --> $DIR/database-syntax.rs:31:1 + | +31 | / #[database("foo")] +32 | | struct H { +33 | | foo: deadpool_postgres::Pool, +34 | | } + | |_^ + | +note: error occurred while deriving `Database` + --> $DIR/database-syntax.rs:30:10 + | +30 | #[derive(Database)] + | ^^^^^^^^ + = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.rs b/contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.rs new file mode 120000 index 00000000..98c58fba --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.rs @@ -0,0 +1 @@ +../ui-fail/database-types.rs \ No newline at end of file diff --git a/contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.stderr b/contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.stderr new file mode 100644 index 00000000..7ab774e4 --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `Unknown: Pool` is not satisfied + --> $DIR/database-types.rs:7:10 + | +7 | struct A(Unknown); + | ^^^^^^^ the trait `Pool` is not implemented for `Unknown` + | + ::: $WORKSPACE/contrib/db_pools/lib/src/database.rs + | + | type Pool: Pool; + | ---- required by this bound in `rocket_db_pools::Database::Pool` + +error[E0277]: the trait bound `Vec: Pool` is not satisfied + --> $DIR/database-types.rs:11:10 + | +11 | struct B(Vec); + | ^^^^^^^^ the trait `Pool` is not implemented for `Vec` + | + ::: $WORKSPACE/contrib/db_pools/lib/src/database.rs + | + | type Pool: Pool; + | ---- required by this bound in `rocket_db_pools::Database::Pool` diff --git a/contrib/db_pools/codegen/tests/ui-fail-stable/database-syntax.rs b/contrib/db_pools/codegen/tests/ui-fail-stable/database-syntax.rs new file mode 120000 index 00000000..717e99bd --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail-stable/database-syntax.rs @@ -0,0 +1 @@ +../ui-fail/database-syntax.rs \ No newline at end of file diff --git a/contrib/db_pools/codegen/tests/ui-fail-stable/database-syntax.stderr b/contrib/db_pools/codegen/tests/ui-fail-stable/database-syntax.stderr new file mode 100644 index 00000000..34c30028 --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail-stable/database-syntax.stderr @@ -0,0 +1,111 @@ +error: invalid value: expected string literal + --> $DIR/database-syntax.rs:4:12 + | +4 | #[database(123)] + | ^^^ + +error: [note] error occurred while deriving `Database` + --> $DIR/database-syntax.rs:3:10 + | +3 | #[derive(Database)] + | ^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected key/value `key = value` + --> $DIR/database-syntax.rs:8:25 + | +8 | #[database("some-name", "another")] + | ^^^^^^^^^ + +error: [note] error occurred while deriving `Database` + --> $DIR/database-syntax.rs:7:10 + | +7 | #[derive(Database)] + | ^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected attribute parameter: `name` + --> $DIR/database-syntax.rs:12:25 + | +12 | #[database("some-name", name = "another")] + | ^^^^ + +error: [note] error occurred while deriving `Database` + --> $DIR/database-syntax.rs:11:10 + | +11 | #[derive(Database)] + | ^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: enums are not supported + --> $DIR/database-syntax.rs:16:1 + | +16 | #[database("foo")] + | ^ + +error: [note] error occurred while deriving `Database` + --> $DIR/database-syntax.rs:15:10 + | +15 | #[derive(Database)] + | ^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: missing `#[database("name")]` attribute + --> $DIR/database-syntax.rs:20:1 + | +20 | struct E(deadpool_postgres::Pool); + | ^^^^^^ + +error: [note] error occurred while deriving `Database` + --> $DIR/database-syntax.rs:19:10 + | +19 | #[derive(Database)] + | ^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: struct must have exactly one unnamed field + --> $DIR/database-syntax.rs:23:1 + | +23 | #[database("foo")] + | ^ + +error: [note] error occurred while deriving `Database` + --> $DIR/database-syntax.rs:22:10 + | +22 | #[derive(Database)] + | ^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: struct must have exactly one unnamed field + --> $DIR/database-syntax.rs:27:1 + | +27 | #[database("foo")] + | ^ + +error: [note] error occurred while deriving `Database` + --> $DIR/database-syntax.rs:26:10 + | +26 | #[derive(Database)] + | ^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: named structs are not supported + --> $DIR/database-syntax.rs:31:1 + | +31 | #[database("foo")] + | ^ + +error: [note] error occurred while deriving `Database` + --> $DIR/database-syntax.rs:30:10 + | +30 | #[derive(Database)] + | ^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/contrib/db_pools/codegen/tests/ui-fail-stable/database-types.rs b/contrib/db_pools/codegen/tests/ui-fail-stable/database-types.rs new file mode 120000 index 00000000..98c58fba --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail-stable/database-types.rs @@ -0,0 +1 @@ +../ui-fail/database-types.rs \ No newline at end of file diff --git a/contrib/db_pools/codegen/tests/ui-fail-stable/database-types.stderr b/contrib/db_pools/codegen/tests/ui-fail-stable/database-types.stderr new file mode 100644 index 00000000..30b52af1 --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail-stable/database-types.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `Unknown: Pool` is not satisfied + --> $DIR/database-types.rs:7:10 + | +7 | struct A(Unknown); + | ^^^^^^^ the trait `Pool` is not implemented for `Unknown` + | + ::: $WORKSPACE/contrib/db_pools/lib/src/database.rs + | + | type Pool: Pool; + | ---- required by this bound in `rocket_db_pools::Database::Pool` + +error[E0277]: the trait bound `Vec: Pool` is not satisfied + --> $DIR/database-types.rs:11:10 + | +11 | struct B(Vec); + | ^^^ the trait `Pool` is not implemented for `Vec` + | + ::: $WORKSPACE/contrib/db_pools/lib/src/database.rs + | + | type Pool: Pool; + | ---- required by this bound in `rocket_db_pools::Database::Pool` diff --git a/contrib/db_pools/codegen/tests/ui-fail.rs b/contrib/db_pools/codegen/tests/ui-fail.rs new file mode 100644 index 00000000..1cd5552a --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail.rs @@ -0,0 +1,10 @@ +#[test] +fn ui() { + let path = match version_check::is_feature_flaggable() { + Some(true) => "ui-fail-nightly", + _ => "ui-fail-stable" + }; + + let t = trybuild::TestCases::new(); + t.compile_fail(format!("tests/{}/*.rs", path)); +} diff --git a/contrib/db_pools/codegen/tests/ui-fail/database-syntax.rs b/contrib/db_pools/codegen/tests/ui-fail/database-syntax.rs new file mode 100644 index 00000000..a90e105d --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail/database-syntax.rs @@ -0,0 +1,36 @@ +use rocket_db_pools::{deadpool_postgres, Database}; + +#[derive(Database)] +#[database(123)] +struct A(deadpool_postgres::Pool); + +#[derive(Database)] +#[database("some-name", "another")] +struct B(deadpool_postgres::Pool); + +#[derive(Database)] +#[database("some-name", name = "another")] +struct C(deadpool_postgres::Pool); + +#[derive(Database)] +#[database("foo")] +enum D { } + +#[derive(Database)] +struct E(deadpool_postgres::Pool); + +#[derive(Database)] +#[database("foo")] +struct F; + +#[derive(Database)] +#[database("foo")] +struct G(deadpool_postgres::Pool, deadpool_postgres::Pool); + +#[derive(Database)] +#[database("foo")] +struct H { + foo: deadpool_postgres::Pool, +} + +fn main() { } diff --git a/contrib/db_pools/codegen/tests/ui-fail/database-types.rs b/contrib/db_pools/codegen/tests/ui-fail/database-types.rs new file mode 100644 index 00000000..d4e1c585 --- /dev/null +++ b/contrib/db_pools/codegen/tests/ui-fail/database-types.rs @@ -0,0 +1,13 @@ +#[macro_use] extern crate rocket_db_pools; + +struct Unknown; + +#[derive(Database)] +#[database("foo")] +struct A(Unknown); + +#[derive(Database)] +#[database("bar")] +struct B(Vec); + +fn main() { } diff --git a/scripts/config.sh b/scripts/config.sh index 6950740b..8eb6e78d 100755 --- a/scripts/config.sh +++ b/scripts/config.sh @@ -84,6 +84,11 @@ CONTRIB_SYNC_DB_POOLS_CRATE_ROOTS=( "${CONTRIB_ROOT}/sync_db_pools/codegen" ) +CONTRIB_DB_POOLS_CRATE_ROOTS=( + "${CONTRIB_ROOT}/db_pools/lib" + "${CONTRIB_ROOT}/db_pools/codegen" +) + ALL_CRATE_ROOTS=( "${CORE_HTTP_ROOT}" "${CORE_CODEGEN_ROOT}" diff --git a/scripts/test.sh b/scripts/test.sh index 16956841..1e559f73 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -189,6 +189,9 @@ check_versions_match "${CORE_CRATE_ROOTS[@]}" echo ":: Ensuring contrib sync_db_pools versions match..." check_versions_match "${CONTRIB_SYNC_DB_POOLS_CRATE_ROOTS[@]}" +echo ":: Ensuring contrib db_pools versions match..." +check_versions_match "${CONTRIB_SYNC_DB_POOLS_CRATE_ROOTS[@]}" + echo ":: Ensuring minimum style requirements are met..." check_style