Skip to content

Commit

Permalink
Update to syn 2 and serde_derive_internals 0.29
Browse files Browse the repository at this point in the history
  • Loading branch information
GREsau committed Apr 28, 2024
1 parent e04e3a3 commit 9501fe3
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 235 deletions.
1 change: 1 addition & 0 deletions schemars/tests/remote_derive_generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum OrDef<A, B> {

struct Str<'a>(&'a str);

#[allow(dead_code)]
#[derive(JsonSchema, Serialize)]
#[serde(remote = "Str")]
struct StrDef<'a>(&'a str);
Expand Down
1 change: 1 addition & 0 deletions schemars/tests/schema_with_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ fn struct_normal() -> TestResult {
test_default_generated_schema::<Struct>("schema_with-struct")
}

#[allow(dead_code)]
#[derive(JsonSchema)]
pub struct Tuple(
#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema,
Expand Down
1 change: 1 addition & 0 deletions schemars/tests/skip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ fn skip_struct_fields() -> TestResult {
test_default_generated_schema::<MyStruct>("skip_struct_fields")
}

#[allow(dead_code)]
#[derive(JsonSchema)]
struct TupleStruct(
#[schemars(skip)] i32,
Expand Down
2 changes: 2 additions & 0 deletions schemars/tests/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ fn struct_normal() -> TestResult {
test_default_generated_schema::<Struct>("struct-normal")
}

#[allow(dead_code)]
#[derive(JsonSchema)]
pub struct Tuple(i32, bool, Option<&'static str>);

Expand All @@ -26,6 +27,7 @@ fn struct_tuple() -> TestResult {
test_default_generated_schema::<Tuple>("struct-tuple")
}

#[allow(dead_code)]
#[derive(JsonSchema)]
pub struct Newtype(i32);

Expand Down
2 changes: 2 additions & 0 deletions schemars/tests/transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ pub struct TransparentStruct {
inner: (),
}

#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(transparent)]
pub struct TransparentNewType(Option<InnerStruct>);

#[allow(dead_code)]
#[derive(JsonSchema)]
pub struct InnerStruct(String, i32);

Expand Down
2 changes: 2 additions & 0 deletions schemars/tests/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ fn validate_schemars_attrs() -> TestResult {
test_default_generated_schema::<Struct2>("validate_schemars_attrs")
}

#[allow(dead_code)]
#[derive(JsonSchema)]
pub struct Tuple(
#[validate(range(max = 10))] u8,
Expand All @@ -115,6 +116,7 @@ fn validate_tuple() -> TestResult {
test_default_generated_schema::<Tuple>("validate_tuple")
}

#[allow(dead_code)]
#[derive(JsonSchema)]
pub struct NewType(#[validate(range(max = 10))] u8);

Expand Down
2 changes: 1 addition & 1 deletion schemars/tests/validate_inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub struct Struct<'a> {
#[schemars(inner(length(min = 5, max = 100)))]
array_str_length: [&'a str; 2],
#[schemars(inner(contains(pattern = "substring...")))]
slice_str_contains: &'a[&'a str],
slice_str_contains: &'a [&'a str],
#[schemars(inner(regex = "STARTS_WITH_HELLO"))]
vec_str_regex: Vec<String>,
#[schemars(inner(length(min = 1, max = 100)))]
Expand Down
4 changes: 2 additions & 2 deletions schemars_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ proc-macro = true
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0", features = ["extra-traits"] }
serde_derive_internals = "0.26.0"
syn = { version = "2.0", features = ["extra-traits"] }
serde_derive_internals = "0.29"

[dev-dependencies]
pretty_assertions = "1.2.1"
8 changes: 4 additions & 4 deletions schemars_derive/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub struct Field<'a> {
}

impl<'a> Container<'a> {
pub fn from_ast(item: &'a syn::DeriveInput) -> Result<Container<'a>, Vec<syn::Error>> {
pub fn from_ast(item: &'a syn::DeriveInput) -> syn::Result<Container<'a>> {
let ctxt = Ctxt::new();
let result = serde_ast::Container::from_ast(&ctxt, item, Derive::Deserialize)
.ok_or(())
Expand All @@ -48,7 +48,7 @@ impl<'a> Container<'a> {
.map(|_| result.expect("from_ast set no errors on Ctxt, so should have returned Ok"))
}

pub fn name(&self) -> String {
pub fn name(&self) -> &str {
self.serde_attrs.name().deserialize_name()
}

Expand All @@ -64,7 +64,7 @@ impl<'a> Container<'a> {
}

impl<'a> Variant<'a> {
pub fn name(&self) -> String {
pub fn name(&self) -> &str {
self.serde_attrs.name().deserialize_name()
}

Expand All @@ -74,7 +74,7 @@ impl<'a> Variant<'a> {
}

impl<'a> Field<'a> {
pub fn name(&self) -> String {
pub fn name(&self) -> &str {
self.serde_attrs.name().deserialize_name()
}
}
14 changes: 9 additions & 5 deletions schemars_derive/src/attr/doc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use syn::{Attribute, Lit::Str, Meta::NameValue, MetaNameValue};
use syn::Attribute;

pub fn get_title_and_desc_from_doc(attrs: &[Attribute]) -> (Option<String>, Option<String>) {
let doc = match get_doc(attrs) {
Expand Down Expand Up @@ -35,13 +35,17 @@ fn get_doc(attrs: &[Attribute]) -> Option<String> {
let attrs = attrs
.iter()
.filter_map(|attr| {
if !attr.path.is_ident("doc") {
if !attr.path().is_ident("doc") {
return None;
}

let meta = attr.parse_meta().ok()?;
if let NameValue(MetaNameValue { lit: Str(s), .. }) = meta {
return Some(s.value());
let meta = attr.meta.require_name_value().ok()?;
if let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit_str),
..
}) = &meta.value
{
return Some(lit_str.value());
}

None
Expand Down
100 changes: 49 additions & 51 deletions schemars_derive/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ use proc_macro2::{Group, Span, TokenStream, TokenTree};
use quote::ToTokens;
use serde_derive_internals::Ctxt;
use syn::parse::{self, Parse};
use syn::Meta::{List, NameValue};
use syn::MetaNameValue;
use syn::NestedMeta::{Lit, Meta};
use syn::{Meta, MetaNameValue};

// FIXME using the same struct for containers+variants+fields means that
// with/schema_with are accepted (but ignored) on containers, and
Expand Down Expand Up @@ -42,10 +40,10 @@ impl Attrs {
.populate(attrs, "schemars", false, errors)
.populate(attrs, "serde", true, errors);

result.deprecated = attrs.iter().any(|a| a.path.is_ident("deprecated"));
result.deprecated = attrs.iter().any(|a| a.path().is_ident("deprecated"));
result.repr = attrs
.iter()
.find(|a| a.path.is_ident("repr"))
.find(|a| a.path().is_ident("repr"))
.and_then(|a| a.parse_args().ok());

let (doc_title, doc_description) = doc::get_title_and_desc_from_doc(attrs);
Expand Down Expand Up @@ -105,8 +103,8 @@ impl Attrs {

for meta_item in get_meta_items(attrs, attr_type, errors, ignore_errors) {
match &meta_item {
Meta(NameValue(m)) if m.path.is_ident("with") => {
if let Ok(ty) = parse_lit_into_ty(errors, attr_type, "with", &m.lit) {
Meta::NameValue(m) if m.path.is_ident("with") => {
if let Ok(ty) = parse_lit_into_ty(errors, attr_type, "with", &m.value) {
match self.with {
Some(WithAttr::Type(_)) => duplicate_error(m),
Some(WithAttr::Function(_)) => mutual_exclusive_error(m, "schema_with"),
Expand All @@ -115,8 +113,9 @@ impl Attrs {
}
}

Meta(NameValue(m)) if m.path.is_ident("schema_with") => {
if let Ok(fun) = parse_lit_into_path(errors, attr_type, "schema_with", &m.lit) {
Meta::NameValue(m) if m.path.is_ident("schema_with") => {
if let Ok(fun) = parse_lit_into_path(errors, attr_type, "schema_with", &m.value)
{
match self.with {
Some(WithAttr::Function(_)) => duplicate_error(m),
Some(WithAttr::Type(_)) => mutual_exclusive_error(m, "with"),
Expand All @@ -125,34 +124,36 @@ impl Attrs {
}
}

Meta(NameValue(m)) if m.path.is_ident("title") => {
if let Ok(title) = get_lit_str(errors, attr_type, "title", &m.lit) {
Meta::NameValue(m) if m.path.is_ident("title") => {
if let Ok(title) = expr_as_lit_str(errors, attr_type, "title", &m.value) {
match self.title {
Some(_) => duplicate_error(m),
None => self.title = Some(title.value()),
}
}
}

Meta(NameValue(m)) if m.path.is_ident("description") => {
if let Ok(description) = get_lit_str(errors, attr_type, "description", &m.lit) {
Meta::NameValue(m) if m.path.is_ident("description") => {
if let Ok(description) =
expr_as_lit_str(errors, attr_type, "description", &m.value)
{
match self.description {
Some(_) => duplicate_error(m),
None => self.description = Some(description.value()),
}
}
}

Meta(NameValue(m)) if m.path.is_ident("example") => {
if let Ok(fun) = parse_lit_into_path(errors, attr_type, "example", &m.lit) {
Meta::NameValue(m) if m.path.is_ident("example") => {
if let Ok(fun) = parse_lit_into_path(errors, attr_type, "example", &m.value) {
self.examples.push(fun)
}
}

Meta(NameValue(m)) if m.path.is_ident("rename") => self.is_renamed = true,
Meta::NameValue(m) if m.path.is_ident("rename") => self.is_renamed = true,

Meta(NameValue(m)) if m.path.is_ident("crate") && attr_type == "schemars" => {
if let Ok(p) = parse_lit_into_path(errors, attr_type, "crate", &m.lit) {
Meta::NameValue(m) if m.path.is_ident("crate") && attr_type == "schemars" => {
if let Ok(p) = parse_lit_into_path(errors, attr_type, "crate", &m.value) {
if self.crate_name.is_some() {
duplicate_error(m)
} else {
Expand All @@ -163,14 +164,14 @@ impl Attrs {

_ if ignore_errors => {}

Meta(List(m)) if m.path.is_ident("inner") && attr_type == "schemars" => {
Meta::List(m) if m.path.is_ident("inner") && attr_type == "schemars" => {
// This will be processed with the validation attributes.
// It's allowed only for the schemars attribute because the
// validator crate doesn't support it yet.
}

Meta(meta_item) => {
if !is_known_serde_or_validation_keyword(meta_item) {
_ => {
if !is_known_serde_or_validation_keyword(&meta_item) {
let path = meta_item
.path()
.into_token_stream()
Expand All @@ -182,10 +183,6 @@ impl Attrs {
);
}
}

Lit(lit) => {
errors.error_spanned_by(lit, "unexpected literal in schemars attribute");
}
}
}
self
Expand Down Expand Up @@ -220,34 +217,35 @@ fn get_meta_items(
attr_type: &'static str,
errors: &Ctxt,
ignore_errors: bool,
) -> Vec<syn::NestedMeta> {
attrs.iter().fold(vec![], |mut acc, attr| {
if !attr.path.is_ident(attr_type) {
return acc;
}
match attr.parse_meta() {
Ok(List(meta)) => acc.extend(meta.nested),
Ok(other) if !ignore_errors => {
errors.error_spanned_by(other, format!("expected #[{}(...)]", attr_type))
}
Err(err) if !ignore_errors => errors.error_spanned_by(attr, err),
_ => (),
) -> Vec<Meta> {
let mut result = vec![];
for attr in attrs.iter().filter(|a| a.path().is_ident(attr_type)) {
match attr.parse_args_with(syn::punctuated::Punctuated::<Meta, Token![,]>::parse_terminated)
{
Ok(list) => result.extend(list),
Err(err) if !ignore_errors => errors.syn_error(err),
Err(_) => {}
}
acc
})
}

result
}

fn get_lit_str<'a>(
fn expr_as_lit_str<'a>(
cx: &Ctxt,
attr_type: &'static str,
meta_item_name: &'static str,
lit: &'a syn::Lit,
expr: &'a syn::Expr,
) -> Result<&'a syn::LitStr, ()> {
if let syn::Lit::Str(lit) = lit {
Ok(lit)
if let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit_str),
..
}) = expr
{
Ok(lit_str)
} else {
cx.error_spanned_by(
lit,
expr,
format!(
"expected {} {} attribute to be a string: `{} = \"...\"`",
attr_type, meta_item_name, meta_item_name
Expand All @@ -261,9 +259,9 @@ fn parse_lit_into_ty(
cx: &Ctxt,
attr_type: &'static str,
meta_item_name: &'static str,
lit: &syn::Lit,
lit: &syn::Expr,
) -> Result<syn::Type, ()> {
let string = get_lit_str(cx, attr_type, meta_item_name, lit)?;
let string = expr_as_lit_str(cx, attr_type, meta_item_name, lit)?;

parse_lit_str(string).map_err(|_| {
cx.error_spanned_by(
Expand All @@ -281,17 +279,17 @@ fn parse_lit_into_path(
cx: &Ctxt,
attr_type: &'static str,
meta_item_name: &'static str,
lit: &syn::Lit,
expr: &syn::Expr,
) -> Result<syn::Path, ()> {
let string = get_lit_str(cx, attr_type, meta_item_name, lit)?;
let lit_str = expr_as_lit_str(cx, attr_type, meta_item_name, expr)?;

parse_lit_str(string).map_err(|_| {
parse_lit_str(lit_str).map_err(|_| {
cx.error_spanned_by(
lit,
expr,
format!(
"failed to parse path: `{} = {:?}`",
meta_item_name,
string.value()
lit_str.value()
),
)
})
Expand Down
Loading

0 comments on commit 9501fe3

Please sign in to comment.