diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 0726b02bd..c518007a0 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -198,28 +198,37 @@ method_macro!(Options, options); method_macro!(Trace, trace); method_macro!(Patch, patch); -/// Creates scope. +/// Prepends a path prefix to all handlers using routing macros inside the attached module. /// -/// Syntax: `#[scope("/path")]` +/// # Syntax /// -/// ## Attributes: +/// ``` +/// # use actix_web_codegen::scope; +/// #[scope("/prefix")] +/// mod api { +/// // ... +/// } +/// ``` /// -/// - `"/prefix"` - Raw literal string with path for which to register handler. Mandatory. +/// # Arguments +/// +/// - `"/prefix"` - Raw literal string to be prefixed onto contained handlers' paths. /// /// # Example /// /// ``` -/// # use actix_web_codegen::scope; -/// #[scope("/test")] -/// mod scope_module { -/// # use actix_web_codegen::get; -/// # use actix_web::{HttpResponse, Responder}; -/// #[get("/test")] -/// pub async fn test() -> impl Responder { -/// // this has path /test/test -/// HttpResponse::Ok().finish() +/// # use actix_web_codegen::{scope, get}; +/// # use actix_web::Responder; +/// #[scope("/api")] +/// mod api { +/// # use super::*; +/// #[get("/hello")] +/// pub async fn hello() -> impl Responder { +/// // this has path /api/hello +/// "Hello, world!" /// } /// } +/// # fn main() {} /// ``` #[proc_macro_attribute] pub fn scope(args: TokenStream, input: TokenStream) -> TokenStream { diff --git a/actix-web-codegen/src/scope.rs b/actix-web-codegen/src/scope.rs index 12c1c7e2b..1748671b7 100644 --- a/actix-web-codegen/src/scope.rs +++ b/actix-web-codegen/src/scope.rs @@ -1,7 +1,6 @@ use proc_macro::TokenStream; use proc_macro2::{Span, TokenStream as TokenStream2}; -use quote::quote; -use syn::LitStr; +use quote::{quote, ToTokens as _}; use crate::{ input_and_compile_error, @@ -17,7 +16,6 @@ pub fn with_scope(args: TokenStream, input: TokenStream) -> TokenStream { fn with_scope_inner(args: TokenStream, input: TokenStream) -> syn::Result { if args.is_empty() { - // macro args are missing return Err(syn::Error::new( Span::call_site(), "missing arguments for scope macro, \ @@ -25,8 +23,7 @@ fn with_scope_inner(args: TokenStream, input: TokenStream) -> syn::Result(args.clone()).map_err(|err| { - // first macro arg is not a string literal + let scope_prefix = syn::parse::(args.clone()).map_err(|err| { syn::Error::new( err.span(), "argument to scope macro is not a string literal, \ @@ -40,7 +37,7 @@ fn with_scope_inner(args: TokenStream, input: TokenStream) -> syn::Result syn::Result bool { #[scope("/test")] mod scope_module { + // ensure that imports can be brought into the scope use super::*; #[get("/test/guard", guard = "image_guard")] diff --git a/justfile b/justfile index d92f4bd3d..655540b09 100644 --- a/justfile +++ b/justfile @@ -32,6 +32,10 @@ all_crate_features := if os() == "linux" { "--features='" + non_linux_all_features_list + "'" } +# Run Clippy over workspace. +clippy toolchain="": + cargo {{ toolchain }} clippy --workspace --all-targets {{ all_crate_features }} + # Test workspace using MSRV. test-msrv: downgrade-for-msrv (test msrv_rustup)