Skip to content

Commit 7d29efe

Browse files
authored
Update syn to 2.0 (#56)
1 parent 29c0f6d commit 7d29efe

File tree

8 files changed

+82
-50
lines changed

8 files changed

+82
-50
lines changed

.github/workflows/rust.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
- uses: actions/checkout@v3
5858
- uses: dtolnay/rust-toolchain@master
5959
with:
60-
toolchain: "1.66"
60+
toolchain: "1.68"
6161
id: rust-toolchain
6262
- uses: actions/cache@v3
6363
with:

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,5 @@ uuid08 = { package = "uuid", version = "0.8", optional = true }
3737
[dev-dependencies]
3838
paste = "1.0"
3939
pretty_assertions = "1.0"
40-
serde = { version = "1.0", features = ["derive"] }
40+
serde = { version = "1.0.158", features = ["derive"] }
4141
trybuild = "=1.0.79"

derive/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ proc-macro = true
1717
[dependencies]
1818
proc-macro2 = "1.0"
1919
quote = "1.0"
20-
serde_derive_internals = "0.26"
21-
syn = "1.0"
22-
syn-path = "1.0"
20+
serde_derive_internals = "0.27"
21+
syn = "2.0"
22+
syn-path = "2.0"

derive/src/attrs.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
use crate::util::ExpectLit;
2-
use syn::{punctuated::Punctuated, spanned::Spanned as _, Attribute, LitStr, Meta, Token};
2+
use proc_macro2::TokenStream;
3+
use syn::{
4+
parse::{Parse, ParseStream},
5+
punctuated::Punctuated,
6+
spanned::Spanned as _,
7+
Attribute, LitStr, Meta, Token
8+
};
39

410
pub(super) fn parse_doc_attr(input: &Attribute) -> syn::Result<Option<LitStr>> {
5-
input.parse_meta().and_then(|meta| {
6-
Ok(match meta {
7-
Meta::NameValue(kv) => Some(kv.lit.expect_str()?),
8-
_ => None
9-
})
11+
Ok(match &input.meta {
12+
Meta::NameValue(kv) => Some(kv.value.clone().expect_str()?),
13+
_ => None
1014
})
1115
}
1216

@@ -36,25 +40,33 @@ pub(super) struct ContainerAttributes {
3640
pub(super) deny_unknown_fields: bool
3741
}
3842

43+
struct ParseHelper(Punctuated<Meta, Token![,]>);
44+
45+
impl Parse for ParseHelper {
46+
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
47+
Ok(Self(Punctuated::parse_terminated(input)?))
48+
}
49+
}
50+
3951
impl ContainerAttributes {
40-
pub(super) fn parse_from(&mut self, input: &Attribute, error_on_unknown: bool) -> syn::Result<()> {
41-
let tokens: Punctuated<Meta, Token![,]> = input.parse_args_with(Punctuated::parse_terminated)?;
52+
pub(super) fn parse_from(&mut self, tokens: TokenStream, error_on_unknown: bool) -> syn::Result<()> {
53+
let tokens = syn::parse2::<ParseHelper>(tokens)?.0;
4254
for token in tokens {
4355
match token {
4456
Meta::NameValue(kv) if kv.path.is_ident("rename") => {
45-
self.rename = Some(kv.lit.expect_str()?);
57+
self.rename = Some(kv.value.expect_str()?);
4658
},
4759

4860
Meta::NameValue(kv) if kv.path.is_ident("rename_all") => {
49-
self.rename_all = Some(kv.lit.expect_str()?);
61+
self.rename_all = Some(kv.value.expect_str()?);
5062
},
5163

5264
Meta::NameValue(kv) if kv.path.is_ident("tag") => {
53-
self.tag = Some(kv.lit.expect_str()?);
65+
self.tag = Some(kv.value.expect_str()?);
5466
},
5567

5668
Meta::NameValue(kv) if kv.path.is_ident("content") => {
57-
self.content = Some(kv.lit.expect_str()?);
69+
self.content = Some(kv.value.expect_str()?);
5870
},
5971

6072
Meta::Path(path) if path.is_ident("untagged") => {
@@ -87,12 +99,12 @@ pub(super) struct FieldAttributes {
8799
}
88100

89101
impl FieldAttributes {
90-
pub(super) fn parse_from(&mut self, input: &Attribute, error_on_unknown: bool) -> syn::Result<()> {
91-
let tokens: Punctuated<Meta, Token![,]> = input.parse_args_with(Punctuated::parse_terminated)?;
102+
pub(super) fn parse_from(&mut self, tokens: TokenStream, error_on_unknown: bool) -> syn::Result<()> {
103+
let tokens = syn::parse2::<ParseHelper>(tokens)?.0;
92104
for token in tokens {
93105
match token {
94106
Meta::NameValue(kv) if kv.path.is_ident("rename") => {
95-
self.rename = Some(kv.lit.expect_str()?);
107+
self.rename = Some(kv.value.expect_str()?);
96108
},
97109

98110
Meta::Path(path) if path.is_ident("default") => {

derive/src/lib.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use proc_macro::TokenStream;
99
use proc_macro2::TokenStream as TokenStream2;
1010
use quote::quote;
11-
use syn::{parse_macro_input, Data, DeriveInput, TraitBound, TraitBoundModifier, TypeParamBound};
11+
use syn::{parse_macro_input, Data, DeriveInput, Meta, TraitBound, TraitBoundModifier, TypeParamBound};
1212
use syn_path::path;
1313

1414
mod attrs;
@@ -28,25 +28,34 @@ pub fn derive_openapi_type(input: TokenStream) -> TokenStream {
2828
expand_openapi_type(input).unwrap_or_else(|err| err.to_compile_error()).into()
2929
}
3030

31+
fn filter_parse_attrs(
32+
attrs: &mut ContainerAttributes,
33+
input: &DeriveInput,
34+
filter: &str,
35+
error_on_unknown: bool
36+
) -> syn::Result<()> {
37+
for attr in &input.attrs {
38+
match &attr.meta {
39+
Meta::List(meta) if meta.path.is_ident(filter) => {
40+
attrs.parse_from(meta.tokens.clone(), error_on_unknown)?;
41+
},
42+
_ => {}
43+
}
44+
}
45+
Ok(())
46+
}
47+
3148
fn expand_openapi_type(mut input: DeriveInput) -> syn::Result<TokenStream2> {
3249
let ident = &input.ident;
3350

3451
// parse #[serde] and #[openapi] attributes
3552
let mut attrs = ContainerAttributes::default();
36-
for attr in &input.attrs {
37-
if attr.path.is_ident("serde") {
38-
attrs.parse_from(attr, false)?;
39-
}
40-
}
41-
for attr in &input.attrs {
42-
if attr.path.is_ident("openapi") {
43-
attrs.parse_from(attr, true)?;
44-
}
45-
}
53+
filter_parse_attrs(&mut attrs, &input, "serde", false)?;
54+
filter_parse_attrs(&mut attrs, &input, "openapi", true)?;
4655

4756
// parse #[doc] attributes
4857
for attr in &input.attrs {
49-
if attr.path.is_ident("doc") {
58+
if attr.path().is_ident("doc") {
5059
if let Some(lit) = parse_doc_attr(attr)? {
5160
attrs.doc.push(lit.value());
5261
}

derive/src/parser.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use crate::{
55
use proc_macro2::{Ident, Span};
66
use serde_derive_internals::attr::RenameRule;
77
use syn::{
8-
punctuated::Punctuated, spanned::Spanned as _, AngleBracketedGenericArguments, DataEnum, DataStruct, DataUnion, Fields,
9-
FieldsNamed, GenericArgument, LitStr, PathArguments, Type, TypePath
8+
punctuated::Punctuated, spanned::Spanned as _, AngleBracketedGenericArguments, DataEnum, DataStruct, DataUnion, Field,
9+
Fields, FieldsNamed, GenericArgument, LitStr, Meta, PathArguments, Type, TypePath
1010
};
1111
use syn_path::path;
1212

@@ -43,21 +43,25 @@ pub(super) enum ParseDataType {
4343
Unit
4444
}
4545

46+
fn filter_parse_attrs(attrs: &mut FieldAttributes, input: &Field, filter: &str, error_on_unknown: bool) -> syn::Result<()> {
47+
for attr in &input.attrs {
48+
match &attr.meta {
49+
Meta::List(meta) if meta.path.is_ident(filter) => {
50+
attrs.parse_from(meta.tokens.clone(), error_on_unknown)?;
51+
},
52+
_ => {}
53+
}
54+
}
55+
Ok(())
56+
}
57+
4658
fn parse_named_fields(named_fields: &FieldsNamed, rename_all: Option<&LitStr>) -> syn::Result<Vec<ParseDataField>> {
4759
let mut fields: Vec<ParseDataField> = Vec::new();
4860
for f in &named_fields.named {
4961
// parse #[serde] and #[openapi] attributes
5062
let mut attrs = FieldAttributes::default();
51-
for attr in &f.attrs {
52-
if attr.path.is_ident("serde") {
53-
attrs.parse_from(attr, false)?;
54-
}
55-
}
56-
for attr in &f.attrs {
57-
if attr.path.is_ident("openapi") {
58-
attrs.parse_from(attr, true)?;
59-
}
60-
}
63+
filter_parse_attrs(&mut attrs, f, "serde", false)?;
64+
filter_parse_attrs(&mut attrs, f, "openapi", true)?;
6165

6266
// skip this field if desired
6367
if attrs.skip_serializing && attrs.skip_deserializing {
@@ -67,7 +71,7 @@ fn parse_named_fields(named_fields: &FieldsNamed, rename_all: Option<&LitStr>) -
6771
// parse #[doc] attributes
6872
let mut doc = Vec::new();
6973
for attr in &f.attrs {
70-
if attr.path.is_ident("doc") {
74+
if attr.path().is_ident("doc") {
7175
if let Some(lit) = parse_doc_attr(attr)? {
7276
doc.push(lit.value());
7377
}
@@ -339,7 +343,7 @@ pub(super) fn parse_enum(ident: &Ident, inum: &DataEnum, attrs: &ContainerAttrib
339343
},
340344
// no variants
341345
(None, None) => Err(syn::Error::new(
342-
inum.brace_token.span,
346+
inum.brace_token.span.span(),
343347
"#[derive(OpenapiType)] does not support enums with no variants"
344348
))
345349
}

derive/src/util.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use proc_macro2::{Ident, Span};
2-
use syn::{Lit, LitStr};
2+
use syn::{spanned::Spanned as _, Expr, Lit, LitStr};
33

44
/// Convert [Ident], [String] and [&str] into a [LitStr].
55
pub(super) trait ToLitStr {
@@ -37,3 +37,12 @@ impl ExpectLit for Lit {
3737
}
3838
}
3939
}
40+
41+
impl ExpectLit for Expr {
42+
fn expect_str(self) -> syn::Result<LitStr> {
43+
match self {
44+
Expr::Lit(lit) => lit.lit.expect_str(),
45+
_ => Err(syn::Error::new(self.span(), "Expected string literal"))
46+
}
47+
}
48+
}

tests/fail/not_openapitype_generics.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@ error[E0599]: the function or associated item `schema` exists for struct `Foo<Ba
1515
|
1616
= note: trait bound `Bar: OpenapiType` was not satisfied
1717
= note: the following trait bounds were not satisfied:
18-
`Bar: OpenapiType`
19-
which is required by `Foo<Bar>: OpenapiType`
2018
`Foo<Bar>: OpenapiType`
2119
which is required by `&Foo<Bar>: OpenapiType`
22-
note: the following trait must be implemented
20+
note: the trait `OpenapiType` must be implemented
2321
--> src/lib.rs
2422
|
2523
| pub trait OpenapiType {

0 commit comments

Comments
 (0)