Skip to content

Commit

Permalink
Upgrade to syn 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Ogeon committed Apr 9, 2023
1 parent 021d962 commit 10aa5d6
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 106 deletions.
4 changes: 2 additions & 2 deletions palette_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "palette_derive"
version = "0.6.1" #automatically updated
version = "0.6.1" #automatically updated
authors = ["Erik Hedvall <hello@erikhedvall.nu>"]
exclude = []
description = "Automatically implement traits from the palette crate."
Expand All @@ -17,7 +17,7 @@ proc-macro = true
bench = false

[dependencies]
syn = { version = "^1.0", default-features = false, features = [
syn = { version = "2.0.13", default-features = false, features = [
"derive",
"parsing",
"printing",
Expand Down
26 changes: 20 additions & 6 deletions palette_derive/src/cast/array_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use proc_macro::TokenStream;
use proc_macro2::Span;

use quote::{quote, ToTokens};
use syn::{Attribute, Data, DeriveInput, Fields, Ident, Type};
use syn::{
punctuated::Punctuated, token::Comma, Attribute, Data, DeriveInput, Fields, Meta, Path, Type,
};

use crate::meta::{self, FieldAttributes, IdentOrIndex, TypeItemAttributes};
use crate::util;
Expand Down Expand Up @@ -125,20 +127,32 @@ fn is_allowed_repr(attributes: &[Attribute]) -> std::result::Result<bool, Vec<sy
let mut errors = Vec::new();

for attribute in attributes {
let attribute_name = attribute.path.get_ident().map(ToString::to_string);
let attribute_name = attribute.path().get_ident().map(ToString::to_string);

if let Some("repr") = attribute_name.as_deref() {
let items = match meta::parse_tuple_attribute(attribute.tokens.clone()) {
let meta_list = match attribute.meta.require_list() {
Ok(list) => list,
Err(error) => {
errors.push(error);
continue;
}
};

let items = match meta_list.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
{
Ok(items) => items,
Err(error) => {
errors.push(error);
continue;
}
};

let contains_allowed_repr = items
.iter()
.any(|item: &Ident| item == "C" || item == "transparent");
let contains_allowed_repr = items.iter().any(|item| {
item.require_path_only()
.ok()
.and_then(Path::get_ident)
.map_or(false, |ident| ident == "C" || ident == "transparent")
});

if contains_allowed_repr {
return Ok(true);
Expand Down
8 changes: 6 additions & 2 deletions palette_derive/src/meta/field_attributes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::{HashMap, HashSet};

use syn::spanned::Spanned;
use syn::{spanned::Spanned, Expr, ExprLit};
use syn::{Lit, Meta, MetaNameValue, Result, Type};

use super::{assert_path_meta, FieldAttributeArgumentParser, IdentOrIndex};
Expand All @@ -23,7 +23,11 @@ impl FieldAttributeArgumentParser for FieldAttributes {
}
Some("unsafe_same_layout_as") => {
let substitute = if let Meta::NameValue(MetaNameValue {
lit: Lit::Str(string),
value:
Expr::Lit(ExprLit {
lit: Lit::Str(string),
..
}),
..
}) = argument
{
Expand Down
98 changes: 32 additions & 66 deletions palette_derive/src/meta/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use proc_macro2::TokenStream;
use syn::parse::{Parse, ParseBuffer, ParseStream, Parser, Result};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{
parenthesized, Attribute, Fields, Ident, Index, Lit, LitStr, Meta, NestedMeta, Token, Type,
parse::{Parse, ParseStream, Parser, Result},
token::Comma,
};
use syn::{Attribute, Fields, Ident, Index, LitStr, Meta, Token, Type};

pub use self::field_attributes::*;
pub use self::type_item_attributes::*;
Expand All @@ -20,7 +21,8 @@ pub fn parse_namespaced_attributes<T: AttributeArgumentParser>(

for attribute in attributes {
let is_palette_attribute = attribute
.path
.meta
.path()
.get_ident()
.map(|name| name == "palette")
.unwrap_or(false);
Expand All @@ -29,25 +31,29 @@ pub fn parse_namespaced_attributes<T: AttributeArgumentParser>(
continue;
}

if attribute.tokens.is_empty() {
let meta_list = match attribute.meta.require_list() {
Ok(list) => list,
Err(error) => {
errors.push(error);
continue;
}
};

if meta_list.tokens.is_empty() {
errors.push(::syn::parse::Error::new(
attribute.path.span(),
attribute.path().span(),
"expected `palette(...)`",
));

continue;
}

let parse_result = parse_meta_list.parse2(attribute.tokens);
let parse_result =
Punctuated::<_, Comma>::parse_terminated.parse2(meta_list.tokens.clone());
match parse_result {
Ok(meta) => {
for argument in meta {
let argument_result = match argument {
NestedMeta::Meta(argument) => result.argument(argument),
NestedMeta::Lit(literal) => result.literal(literal),
};

if let Err(error) = argument_result {
if let Err(error) = result.argument(argument) {
errors.push(error);
}
}
Expand Down Expand Up @@ -84,7 +90,7 @@ pub fn parse_field_attributes<T: FieldAttributeArgumentParser>(

for (field_name, ty, attribute) in attributes {
let is_palette_attribute = attribute
.path
.path()
.get_ident()
.map(|name| name == "palette")
.unwrap_or(false);
Expand All @@ -93,25 +99,29 @@ pub fn parse_field_attributes<T: FieldAttributeArgumentParser>(
continue;
}

if attribute.tokens.is_empty() {
let meta_list = match attribute.meta.require_list() {
Ok(list) => list,
Err(error) => {
errors.push(error);
continue;
}
};

if meta_list.tokens.is_empty() {
errors.push(::syn::parse::Error::new(
attribute.path.span(),
attribute.path().span(),
"expected `palette(...)`",
));

continue;
}

let parse_result = parse_meta_list.parse2(attribute.tokens);
let parse_result =
Punctuated::<_, Comma>::parse_terminated.parse2(meta_list.tokens.clone());
match parse_result {
Ok(meta) => {
for argument in meta {
let argument_result = match argument {
NestedMeta::Meta(argument) => result.argument(&field_name, &ty, argument),
NestedMeta::Lit(literal) => result.literal(&field_name, &ty, literal),
};

if let Err(error) = argument_result {
if let Err(error) = result.argument(&field_name, &ty, argument) {
errors.push(error);
}
}
Expand All @@ -138,34 +148,6 @@ pub fn assert_path_meta(meta: &Meta) -> Result<()> {
Ok(())
}

pub fn parse_tuple_attribute<T: Parse>(tts: TokenStream) -> Result<Vec<T>> {
fn parse_generic_tuple<T: Parse>(input: ParseStream) -> Result<Vec<T>> {
let content;
parenthesized!(content in input);

let mut tuple = Vec::new();
loop {
tuple.push(content.parse()?);
if content.is_empty() {
break;
}
content.parse::<Token![,]>()?;
if content.is_empty() {
break;
}
}
Ok(tuple)
}

parse_generic_tuple.parse2(tts)
}

fn parse_meta_list(buffer: &ParseBuffer) -> syn::Result<Punctuated<NestedMeta, Token![,]>> {
let inner;
parenthesized!(inner in buffer);
syn::punctuated::Punctuated::parse_terminated(&inner)
}

#[derive(PartialEq)]
pub struct KeyValuePair {
pub key: Ident,
Expand Down Expand Up @@ -244,24 +226,8 @@ pub trait DataMetaParser: Default {

pub trait AttributeArgumentParser: Default {
fn argument(&mut self, argument: Meta) -> Result<()>;

fn literal(&mut self, literal: Lit) -> Result<()> {
Err(::syn::parse::Error::new(
literal.span(),
"unexpected literal",
))
}
}

pub trait FieldAttributeArgumentParser: Default {
fn argument(&mut self, field_name: &IdentOrIndex, ty: &Type, argument: Meta) -> Result<()>;

fn literal(&mut self, field_name: &IdentOrIndex, ty: &Type, literal: Lit) -> Result<()> {
let (_, _) = (field_name, ty);

Err(::syn::parse::Error::new(
literal.span(),
"unexpected literal",
))
}
}
58 changes: 28 additions & 30 deletions palette_derive/src/meta/type_item_attributes.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::collections::HashSet;

use quote::quote;
use syn::spanned::Spanned;
use syn::{Ident, Lit, Meta, MetaNameValue, NestedMeta, Result, Type};
use syn::{punctuated::Punctuated, spanned::Spanned, token::Comma, Expr, ExprLit};
use syn::{Ident, Lit, Meta, MetaNameValue, Result, Type};

use super::AttributeArgumentParser;

Expand All @@ -23,41 +23,27 @@ impl AttributeArgumentParser for TypeItemAttributes {

match argument_name.as_deref() {
Some("skip_derives") => {
let result = if let Meta::List(list) = argument {
let skipped: ::std::result::Result<_, _> = list
.nested
.into_iter()
.map(|value| match value {
NestedMeta::Meta(Meta::Path(path)) => {
if let Some(name) = path.get_ident() {
Ok(name.clone())
} else {
Err(path.span())
}
}
value => Err(value.span()),
})
.collect();
if let Meta::List(list) = argument {
let skipped =
list.parse_args_with(Punctuated::<Ident, Comma>::parse_terminated)?;

skipped.map(|values: Vec<Ident>| {
self.skip_derives
.extend(values.into_iter().map(|ident| ident.to_string()));
})
self.skip_derives
.extend(skipped.into_iter().map(|ident| ident.to_string()));
} else {
Err(argument.span())
};

if let Err(span) = result {
return Err(::syn::parse::Error::new(
span,
argument.span(),
"expected `skip_derives` to have a list of color type names, like `skip_derives(Xyz, Luma, Rgb)`",
));
}
}
Some("component") => {
if self.component.is_none() {
let result = if let Meta::NameValue(MetaNameValue {
lit: Lit::Str(ty), ..
value:
Expr::Lit(ExprLit {
lit: Lit::Str(ty), ..
}),
..
}) = argument
{
self.component = Some(ty.parse()?);
Expand All @@ -80,7 +66,11 @@ impl AttributeArgumentParser for TypeItemAttributes {
Some("white_point") => {
if self.white_point.is_none() {
let result = if let Meta::NameValue(MetaNameValue {
lit: Lit::Str(ty), ..
value:
Expr::Lit(ExprLit {
lit: Lit::Str(ty), ..
}),
..
}) = argument
{
self.white_point = Some(ty.parse()?);
Expand All @@ -103,7 +93,11 @@ impl AttributeArgumentParser for TypeItemAttributes {
Some("rgb_standard") => {
if self.rgb_standard.is_none() {
let result = if let Meta::NameValue(MetaNameValue {
lit: Lit::Str(ty), ..
value:
Expr::Lit(ExprLit {
lit: Lit::Str(ty), ..
}),
..
}) = argument
{
self.rgb_standard = Some(ty.parse()?);
Expand All @@ -126,7 +120,11 @@ impl AttributeArgumentParser for TypeItemAttributes {
Some("luma_standard") => {
if self.luma_standard.is_none() {
let result = if let Meta::NameValue(MetaNameValue {
lit: Lit::Str(ty), ..
value:
Expr::Lit(ExprLit {
lit: Lit::Str(ty), ..
}),
..
}) = argument
{
self.luma_standard = Some(ty.parse()?);
Expand Down

0 comments on commit 10aa5d6

Please sign in to comment.