123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894 |
- #![allow(clippy::too_many_lines)]
- #[macro_use]
- mod macros;
- use quote::quote;
- use syn::{Data, DeriveInput};
- #[test]
- fn test_unit() {
- let input = quote! {
- struct Unit;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Inherited,
- ident: "Unit",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- }
- #[test]
- fn test_struct() {
- let input = quote! {
- #[derive(Debug, Clone)]
- pub struct Item {
- pub ident: Ident,
- pub attrs: Vec<Attribute>
- }
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- attrs: [
- Attribute {
- style: Outer,
- path: Path {
- segments: [
- PathSegment {
- ident: "derive",
- arguments: None,
- },
- ],
- },
- tokens: TokenStream(`(Debug , Clone)`),
- },
- ],
- vis: Visibility::Public,
- ident: "Item",
- generics: Generics,
- data: Data::Struct {
- fields: Fields::Named {
- named: [
- Field {
- vis: Visibility::Public,
- ident: Some("ident"),
- colon_token: Some,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "Ident",
- arguments: None,
- },
- ],
- },
- },
- },
- Field {
- vis: Visibility::Public,
- ident: Some("attrs"),
- colon_token: Some,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "Vec",
- arguments: PathArguments::AngleBracketed {
- args: [
- Type(Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "Attribute",
- arguments: None,
- },
- ],
- },
- }),
- ],
- },
- },
- ],
- },
- },
- },
- ],
- },
- },
- }
- "###);
- snapshot!(input.attrs[0].parse_meta().unwrap(), @r###"
- Meta::List {
- path: Path {
- segments: [
- PathSegment {
- ident: "derive",
- arguments: None,
- },
- ],
- },
- nested: [
- Meta(Path(Path {
- segments: [
- PathSegment {
- ident: "Debug",
- arguments: None,
- },
- ],
- })),
- Meta(Path(Path {
- segments: [
- PathSegment {
- ident: "Clone",
- arguments: None,
- },
- ],
- })),
- ],
- }
- "###);
- }
- #[test]
- fn test_union() {
- let input = quote! {
- union MaybeUninit<T> {
- uninit: (),
- value: T
- }
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Inherited,
- ident: "MaybeUninit",
- generics: Generics {
- lt_token: Some,
- params: [
- Type(TypeParam {
- ident: "T",
- }),
- ],
- gt_token: Some,
- },
- data: Data::Union {
- fields: FieldsNamed {
- named: [
- Field {
- vis: Inherited,
- ident: Some("uninit"),
- colon_token: Some,
- ty: Type::Tuple,
- },
- Field {
- vis: Inherited,
- ident: Some("value"),
- colon_token: Some,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "T",
- arguments: None,
- },
- ],
- },
- },
- },
- ],
- },
- },
- }
- "###);
- }
- #[test]
- #[cfg(feature = "full")]
- fn test_enum() {
- let input = quote! {
- /// See the std::result module documentation for details.
- #[must_use]
- pub enum Result<T, E> {
- Ok(T),
- Err(E),
- Surprise = 0isize,
- // Smuggling data into a proc_macro_derive,
- // in the style of https://github.com/dtolnay/proc-macro-hack
- ProcMacroHack = (0, "data").0
- }
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- attrs: [
- Attribute {
- style: Outer,
- path: Path {
- segments: [
- PathSegment {
- ident: "doc",
- arguments: None,
- },
- ],
- },
- tokens: TokenStream(`= r" See the std::result module documentation for details."`),
- },
- Attribute {
- style: Outer,
- path: Path {
- segments: [
- PathSegment {
- ident: "must_use",
- arguments: None,
- },
- ],
- },
- tokens: TokenStream(``),
- },
- ],
- vis: Visibility::Public,
- ident: "Result",
- generics: Generics {
- lt_token: Some,
- params: [
- Type(TypeParam {
- ident: "T",
- }),
- Type(TypeParam {
- ident: "E",
- }),
- ],
- gt_token: Some,
- },
- data: Data::Enum {
- variants: [
- Variant {
- ident: "Ok",
- fields: Fields::Unnamed {
- unnamed: [
- Field {
- vis: Inherited,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "T",
- arguments: None,
- },
- ],
- },
- },
- },
- ],
- },
- },
- Variant {
- ident: "Err",
- fields: Fields::Unnamed {
- unnamed: [
- Field {
- vis: Inherited,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "E",
- arguments: None,
- },
- ],
- },
- },
- },
- ],
- },
- },
- Variant {
- ident: "Surprise",
- fields: Unit,
- discriminant: Some(Expr::Lit {
- lit: 0isize,
- }),
- },
- Variant {
- ident: "ProcMacroHack",
- fields: Unit,
- discriminant: Some(Expr::Field {
- base: Expr::Tuple {
- elems: [
- Expr::Lit {
- lit: 0,
- },
- Expr::Lit {
- lit: "data",
- },
- ],
- },
- member: Unnamed(Index {
- index: 0,
- }),
- }),
- },
- ],
- },
- }
- "###);
- let meta_items: Vec<_> = input
- .attrs
- .into_iter()
- .map(|attr| attr.parse_meta().unwrap())
- .collect();
- snapshot!(meta_items, @r###"
- [
- Meta::NameValue {
- path: Path {
- segments: [
- PathSegment {
- ident: "doc",
- arguments: None,
- },
- ],
- },
- lit: " See the std::result module documentation for details.",
- },
- Path(Path {
- segments: [
- PathSegment {
- ident: "must_use",
- arguments: None,
- },
- ],
- }),
- ]
- "###);
- }
- #[test]
- fn test_attr_with_path() {
- let input = quote! {
- #[::attr_args::identity
- fn main() { assert_eq!(foo(), "Hello, world!"); }]
- struct Dummy;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- attrs: [
- Attribute {
- style: Outer,
- path: Path {
- leading_colon: Some,
- segments: [
- PathSegment {
- ident: "attr_args",
- arguments: None,
- },
- PathSegment {
- ident: "identity",
- arguments: None,
- },
- ],
- },
- tokens: TokenStream(`fn main () { assert_eq ! (foo () , "Hello, world!") ; }`),
- },
- ],
- vis: Inherited,
- ident: "Dummy",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- assert!(input.attrs[0].parse_meta().is_err());
- }
- #[test]
- fn test_attr_with_non_mod_style_path() {
- let input = quote! {
- #[inert <T>]
- struct S;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- attrs: [
- Attribute {
- style: Outer,
- path: Path {
- segments: [
- PathSegment {
- ident: "inert",
- arguments: None,
- },
- ],
- },
- tokens: TokenStream(`< T >`),
- },
- ],
- vis: Inherited,
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- assert!(input.attrs[0].parse_meta().is_err());
- }
- #[test]
- fn test_attr_with_mod_style_path_with_self() {
- let input = quote! {
- #[foo::self]
- struct S;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- attrs: [
- Attribute {
- style: Outer,
- path: Path {
- segments: [
- PathSegment {
- ident: "foo",
- arguments: None,
- },
- PathSegment {
- ident: "self",
- arguments: None,
- },
- ],
- },
- tokens: TokenStream(``),
- },
- ],
- vis: Inherited,
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- snapshot!(input.attrs[0].parse_meta().unwrap(), @r###"
- Path(Path {
- segments: [
- PathSegment {
- ident: "foo",
- arguments: None,
- },
- PathSegment {
- ident: "self",
- arguments: None,
- },
- ],
- })
- "###);
- }
- #[test]
- fn test_pub_restricted() {
- // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
- let input = quote! {
- pub(in m) struct Z(pub(in m::n) u8);
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Visibility::Restricted {
- in_token: Some,
- path: Path {
- segments: [
- PathSegment {
- ident: "m",
- arguments: None,
- },
- ],
- },
- },
- ident: "Z",
- generics: Generics,
- data: Data::Struct {
- fields: Fields::Unnamed {
- unnamed: [
- Field {
- vis: Visibility::Restricted {
- in_token: Some,
- path: Path {
- segments: [
- PathSegment {
- ident: "m",
- arguments: None,
- },
- PathSegment {
- ident: "n",
- arguments: None,
- },
- ],
- },
- },
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "u8",
- arguments: None,
- },
- ],
- },
- },
- },
- ],
- },
- semi_token: Some,
- },
- }
- "###);
- }
- #[test]
- fn test_vis_crate() {
- let input = quote! {
- crate struct S;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Visibility::Crate,
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- }
- #[test]
- fn test_pub_restricted_crate() {
- let input = quote! {
- pub(crate) struct S;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Visibility::Restricted {
- path: Path {
- segments: [
- PathSegment {
- ident: "crate",
- arguments: None,
- },
- ],
- },
- },
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- }
- #[test]
- fn test_pub_restricted_super() {
- let input = quote! {
- pub(super) struct S;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Visibility::Restricted {
- path: Path {
- segments: [
- PathSegment {
- ident: "super",
- arguments: None,
- },
- ],
- },
- },
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- }
- #[test]
- fn test_pub_restricted_in_super() {
- let input = quote! {
- pub(in super) struct S;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Visibility::Restricted {
- in_token: Some,
- path: Path {
- segments: [
- PathSegment {
- ident: "super",
- arguments: None,
- },
- ],
- },
- },
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- }
- #[test]
- fn test_fields_on_unit_struct() {
- let input = quote! {
- struct S;
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Inherited,
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Unit,
- semi_token: Some,
- },
- }
- "###);
- let data = match input.data {
- Data::Struct(data) => data,
- _ => panic!("expected a struct"),
- };
- assert_eq!(0, data.fields.iter().count());
- }
- #[test]
- fn test_fields_on_named_struct() {
- let input = quote! {
- struct S {
- foo: i32,
- pub bar: String,
- }
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Inherited,
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Fields::Named {
- named: [
- Field {
- vis: Inherited,
- ident: Some("foo"),
- colon_token: Some,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "i32",
- arguments: None,
- },
- ],
- },
- },
- },
- Field {
- vis: Visibility::Public,
- ident: Some("bar"),
- colon_token: Some,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "String",
- arguments: None,
- },
- ],
- },
- },
- },
- ],
- },
- },
- }
- "###);
- let data = match input.data {
- Data::Struct(data) => data,
- _ => panic!("expected a struct"),
- };
- snapshot!(data.fields.into_iter().collect::<Vec<_>>(), @r###"
- [
- Field {
- vis: Inherited,
- ident: Some("foo"),
- colon_token: Some,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "i32",
- arguments: None,
- },
- ],
- },
- },
- },
- Field {
- vis: Visibility::Public,
- ident: Some("bar"),
- colon_token: Some,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "String",
- arguments: None,
- },
- ],
- },
- },
- },
- ]
- "###);
- }
- #[test]
- fn test_fields_on_tuple_struct() {
- let input = quote! {
- struct S(i32, pub String);
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Inherited,
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Fields::Unnamed {
- unnamed: [
- Field {
- vis: Inherited,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "i32",
- arguments: None,
- },
- ],
- },
- },
- },
- Field {
- vis: Visibility::Public,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "String",
- arguments: None,
- },
- ],
- },
- },
- },
- ],
- },
- semi_token: Some,
- },
- }
- "###);
- let data = match input.data {
- Data::Struct(data) => data,
- _ => panic!("expected a struct"),
- };
- snapshot!(data.fields.iter().collect::<Vec<_>>(), @r###"
- [
- Field {
- vis: Inherited,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "i32",
- arguments: None,
- },
- ],
- },
- },
- },
- Field {
- vis: Visibility::Public,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "String",
- arguments: None,
- },
- ],
- },
- },
- },
- ]
- "###);
- }
- #[test]
- fn test_ambiguous_crate() {
- let input = quote! {
- // The field type is `(crate::X)` not `crate (::X)`.
- struct S(crate::X);
- };
- snapshot!(input as DeriveInput, @r###"
- DeriveInput {
- vis: Inherited,
- ident: "S",
- generics: Generics,
- data: Data::Struct {
- fields: Fields::Unnamed {
- unnamed: [
- Field {
- vis: Inherited,
- ty: Type::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "crate",
- arguments: None,
- },
- PathSegment {
- ident: "X",
- arguments: None,
- },
- ],
- },
- },
- },
- ],
- },
- semi_token: Some,
- },
- }
- "###);
- }
|