diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 24ab212a8..25d758832 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2021-xx-xx +- Preserve function visibility for routing macros. [#2714] + +[#2714]: https://github.com/actix/actix-web/pull/2714 ## 4.0.1 - 2022-06-11 diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 5ca5616b6..e937bd161 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -19,7 +19,8 @@ //! //! # Single Method Handler //! There is a macro to set up a handler for each of the most common HTTP methods that also define -//! additional guards and route-specific middleware. +//! additional guards and route-specific middleware. This macros will inherit the visibility +//! of the underlying handler. //! //! See docs for: [GET], [POST], [PATCH], [PUT], [DELETE], [HEAD], [CONNECT], [OPTIONS], [TRACE] //! diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index cae3cbd55..23411e22b 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -291,6 +291,7 @@ impl ToTokens for Route { resource_type, doc_attributes, } = self; + let visibility = &ast.vis; let resource_name = resource_name .as_ref() .map_or_else(|| name.to_string(), LitStr::value); @@ -316,7 +317,7 @@ impl ToTokens for Route { let stream = quote! { #(#doc_attributes)* #[allow(non_camel_case_types, missing_docs)] - pub struct #name; + #visibility struct #name; impl ::actix_web::dev::HttpServiceFactory for #name { fn register(self, __config: &mut actix_web::dev::AppService) { diff --git a/actix-web-codegen/tests/trybuild.rs b/actix-web-codegen/tests/trybuild.rs index 13eb84559..1bb691669 100644 --- a/actix-web-codegen/tests/trybuild.rs +++ b/actix-web-codegen/tests/trybuild.rs @@ -6,6 +6,9 @@ fn compile_macros() { t.pass("tests/trybuild/simple.rs"); t.compile_fail("tests/trybuild/simple-fail.rs"); + t.pass("tests/trybuild/visibility-ok.rs"); + t.compile_fail("tests/trybuild/visibility-fail.rs"); + t.pass("tests/trybuild/route-ok.rs"); t.compile_fail("tests/trybuild/route-missing-method-fail.rs"); t.compile_fail("tests/trybuild/route-duplicate-method-fail.rs"); diff --git a/actix-web-codegen/tests/trybuild/visibility-fail.rs b/actix-web-codegen/tests/trybuild/visibility-fail.rs new file mode 100644 index 000000000..2b7cdfa08 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/visibility-fail.rs @@ -0,0 +1,20 @@ +use actix_web::App; + +mod config { + use actix_web_codegen::*; + use actix_web::{Responder, HttpResponse}; + + #[get("/config")] + async fn config() -> impl Responder { + HttpResponse::Ok() + } +} + +#[actix_web::main] +async fn main() { + let srv = actix_test::start(|| App::new().service(config::config)); + + let request = srv.get("/config"); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} diff --git a/actix-web-codegen/tests/trybuild/visibility-fail.stderr b/actix-web-codegen/tests/trybuild/visibility-fail.stderr new file mode 100644 index 000000000..e44acc010 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/visibility-fail.stderr @@ -0,0 +1,12 @@ +error[E0603]: unit struct `config` is private + --> tests/trybuild/visibility-fail.rs:15:63 + | +15 | let srv = actix_test::start(|| App::new().service(config::config)); + | ^^^^^^ private unit struct + | +note: the unit struct `config` is defined here + --> tests/trybuild/visibility-fail.rs:7:5 + | +7 | #[get("/config")] + | ^^^^^^^^^^^^^^^^^ + = note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/actix-web-codegen/tests/trybuild/visibility-ok.rs b/actix-web-codegen/tests/trybuild/visibility-ok.rs new file mode 100644 index 000000000..2f531efe9 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/visibility-ok.rs @@ -0,0 +1,20 @@ +use actix_web::App; + +mod config { + use actix_web_codegen::*; + use actix_web::{Responder, HttpResponse}; + + #[get("/config")] + pub async fn config() -> impl Responder { + HttpResponse::Ok() + } +} + +#[actix_web::main] +async fn main() { + let srv = actix_test::start(|| App::new().service(config::config)); + + let request = srv.get("/config"); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +}