mirror of
https://github.com/tokio-rs/axum.git
synced 2024-11-21 22:56:46 +01:00
parent
64960bb19c
commit
7d58d49817
5 changed files with 84 additions and 2 deletions
|
@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
# Unreleased
|
||||
|
||||
- None.
|
||||
- **added:** Add `#[from_ref(skip)]` to skip implementing `FromRef` for individual fields ([#1537])
|
||||
|
||||
[#1537]: https://github.com/tokio-rs/axum/pull/1537
|
||||
|
||||
# 0.3.0-rc.2 (8. November, 2022)
|
||||
|
||||
|
|
|
@ -82,6 +82,21 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn combine_unary_attribute<K>(a: &mut Option<K>, b: Option<K>) -> syn::Result<()>
|
||||
where
|
||||
K: ToTokens,
|
||||
{
|
||||
if let Some(kw) = b {
|
||||
if a.is_some() {
|
||||
let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
|
||||
let msg = format!("`{}` specified more than once", kw_name);
|
||||
return Err(syn::Error::new_spanned(kw, msg));
|
||||
}
|
||||
*a = Some(kw);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn second<T, K>(tuple: (T, K)) -> K {
|
||||
tuple.1
|
||||
}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::quote_spanned;
|
||||
use syn::{spanned::Spanned, Field, ItemStruct};
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
spanned::Spanned,
|
||||
Field, ItemStruct, Token,
|
||||
};
|
||||
|
||||
use crate::attr_parsing::{combine_unary_attribute, parse_attrs, Combine};
|
||||
|
||||
pub(crate) fn expand(item: ItemStruct) -> TokenStream {
|
||||
item.fields
|
||||
|
@ -11,6 +17,15 @@ pub(crate) fn expand(item: ItemStruct) -> TokenStream {
|
|||
}
|
||||
|
||||
fn expand_field(state: &Ident, idx: usize, field: &Field) -> TokenStream {
|
||||
let FieldAttrs { skip } = match parse_attrs("from_ref", &field.attrs) {
|
||||
Ok(attrs) => attrs,
|
||||
Err(err) => return err.into_compile_error(),
|
||||
};
|
||||
|
||||
if skip.is_some() {
|
||||
return TokenStream::default();
|
||||
}
|
||||
|
||||
let field_ty = &field.ty;
|
||||
let span = field.ty.span();
|
||||
|
||||
|
@ -33,6 +48,42 @@ fn expand_field(state: &Ident, idx: usize, field: &Field) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
mod kw {
|
||||
syn::custom_keyword!(skip);
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(super) struct FieldAttrs {
|
||||
pub(super) skip: Option<kw::skip>,
|
||||
}
|
||||
|
||||
impl Parse for FieldAttrs {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let mut skip = None;
|
||||
|
||||
while !input.is_empty() {
|
||||
let lh = input.lookahead1();
|
||||
if lh.peek(kw::skip) {
|
||||
skip = Some(input.parse()?);
|
||||
} else {
|
||||
return Err(lh.error());
|
||||
}
|
||||
|
||||
let _ = input.parse::<Token![,]>();
|
||||
}
|
||||
|
||||
Ok(Self { skip })
|
||||
}
|
||||
}
|
||||
|
||||
impl Combine for FieldAttrs {
|
||||
fn combine(mut self, other: Self) -> syn::Result<Self> {
|
||||
let Self { skip } = other;
|
||||
combine_unary_attribute(&mut self.skip, skip)?;
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ui() {
|
||||
crate::run_ui_tests("from_ref");
|
||||
|
|
|
@ -589,6 +589,9 @@ pub fn derive_typed_path(input: TokenStream) -> TokenStream {
|
|||
/// struct AppState {
|
||||
/// auth_token: AuthToken,
|
||||
/// database_pool: DatabasePool,
|
||||
/// // fields can also be skipped
|
||||
/// #[from_ref(skip)]
|
||||
/// api_token: String,
|
||||
/// }
|
||||
///
|
||||
/// // So those types can be extracted via `State`
|
||||
|
@ -601,6 +604,7 @@ pub fn derive_typed_path(input: TokenStream) -> TokenStream {
|
|||
/// let state = AppState {
|
||||
/// auth_token,
|
||||
/// database_pool,
|
||||
/// api_token: "secret".to_owned(),
|
||||
/// };
|
||||
///
|
||||
/// let app = Router::new()
|
||||
|
|
10
axum-macros/tests/from_ref/pass/skip.rs
Normal file
10
axum-macros/tests/from_ref/pass/skip.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use axum_macros::FromRef;
|
||||
|
||||
#[derive(Clone, FromRef)]
|
||||
struct AppState {
|
||||
auth_token: String,
|
||||
#[from_ref(skip)]
|
||||
also_string: String,
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in a new issue