mirror of
https://gitee.com/openharmony/third_party_rust_syn
synced 2024-11-27 09:50:41 +00:00
99510ff0c3
Currently fails with: ---- test_mut_self stdout ---- thread 'test_mut_self' panicked at 'Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation', src/punctuated.rs:181:9
353 lines
11 KiB
Rust
353 lines
11 KiB
Rust
#[macro_use]
|
|
mod macros;
|
|
|
|
use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
|
|
use quote::quote;
|
|
use std::iter::FromIterator;
|
|
use syn::Type;
|
|
|
|
#[test]
|
|
fn test_mut_self() {
|
|
syn::parse_str::<Type>("fn(mut self)").unwrap();
|
|
syn::parse_str::<Type>("fn(mut self,)").unwrap();
|
|
syn::parse_str::<Type>("fn(mut self: ())").unwrap();
|
|
syn::parse_str::<Type>("fn(mut self: ...)").unwrap_err();
|
|
syn::parse_str::<Type>("fn(mut self: mut self)").unwrap_err();
|
|
syn::parse_str::<Type>("fn(mut self::T)").unwrap_err();
|
|
}
|
|
|
|
#[test]
|
|
fn test_macro_variable_type() {
|
|
// mimics the token stream corresponding to `$ty<T>`
|
|
let tokens = TokenStream::from_iter(vec![
|
|
TokenTree::Group(Group::new(Delimiter::None, quote! { ty })),
|
|
TokenTree::Punct(Punct::new('<', Spacing::Alone)),
|
|
TokenTree::Ident(Ident::new("T", Span::call_site())),
|
|
TokenTree::Punct(Punct::new('>', Spacing::Alone)),
|
|
]);
|
|
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "ty",
|
|
arguments: PathArguments::AngleBracketed {
|
|
args: [
|
|
Type(Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "T",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
}
|
|
"###);
|
|
|
|
// mimics the token stream corresponding to `$ty::<T>`
|
|
let tokens = TokenStream::from_iter(vec![
|
|
TokenTree::Group(Group::new(Delimiter::None, quote! { ty })),
|
|
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
|
|
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
|
|
TokenTree::Punct(Punct::new('<', Spacing::Alone)),
|
|
TokenTree::Ident(Ident::new("T", Span::call_site())),
|
|
TokenTree::Punct(Punct::new('>', Spacing::Alone)),
|
|
]);
|
|
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "ty",
|
|
arguments: PathArguments::AngleBracketed {
|
|
colon2_token: Some,
|
|
args: [
|
|
Type(Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "T",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
}
|
|
"###);
|
|
}
|
|
|
|
#[test]
|
|
fn test_group_angle_brackets() {
|
|
// mimics the token stream corresponding to `Option<$ty>`
|
|
let tokens = TokenStream::from_iter(vec![
|
|
TokenTree::Ident(Ident::new("Option", Span::call_site())),
|
|
TokenTree::Punct(Punct::new('<', Spacing::Alone)),
|
|
TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })),
|
|
TokenTree::Punct(Punct::new('>', Spacing::Alone)),
|
|
]);
|
|
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Option",
|
|
arguments: PathArguments::AngleBracketed {
|
|
args: [
|
|
Type(Type::Group {
|
|
elem: Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Vec",
|
|
arguments: PathArguments::AngleBracketed {
|
|
args: [
|
|
Type(Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "u8",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
}
|
|
"###);
|
|
}
|
|
|
|
#[test]
|
|
fn test_group_colons() {
|
|
// mimics the token stream corresponding to `$ty::Item`
|
|
let tokens = TokenStream::from_iter(vec![
|
|
TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })),
|
|
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
|
|
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
|
|
TokenTree::Ident(Ident::new("Item", Span::call_site())),
|
|
]);
|
|
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Vec",
|
|
arguments: PathArguments::AngleBracketed {
|
|
args: [
|
|
Type(Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "u8",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
},
|
|
},
|
|
PathSegment {
|
|
ident: "Item",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}
|
|
"###);
|
|
|
|
let tokens = TokenStream::from_iter(vec![
|
|
TokenTree::Group(Group::new(Delimiter::None, quote! { [T] })),
|
|
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
|
|
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
|
|
TokenTree::Ident(Ident::new("Element", Span::call_site())),
|
|
]);
|
|
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::Path {
|
|
qself: Some(QSelf {
|
|
ty: Type::Slice {
|
|
elem: Type::Path {
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "T",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
position: 0,
|
|
}),
|
|
path: Path {
|
|
leading_colon: Some,
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Element",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}
|
|
"###);
|
|
}
|
|
|
|
#[test]
|
|
fn test_trait_object() {
|
|
let tokens = quote!(dyn for<'a> Trait<'a> + 'static);
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::TraitObject {
|
|
dyn_token: Some,
|
|
bounds: [
|
|
Trait(TraitBound {
|
|
modifier: None,
|
|
lifetimes: Some(BoundLifetimes {
|
|
lifetimes: [
|
|
LifetimeDef {
|
|
lifetime: Lifetime {
|
|
ident: "a",
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Trait",
|
|
arguments: PathArguments::AngleBracketed {
|
|
args: [
|
|
Lifetime(Lifetime {
|
|
ident: "a",
|
|
}),
|
|
],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
Lifetime(Lifetime {
|
|
ident: "static",
|
|
}),
|
|
],
|
|
}
|
|
"###);
|
|
|
|
let tokens = quote!(dyn 'a + Trait);
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::TraitObject {
|
|
dyn_token: Some,
|
|
bounds: [
|
|
Lifetime(Lifetime {
|
|
ident: "a",
|
|
}),
|
|
Trait(TraitBound {
|
|
modifier: None,
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Trait",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
}
|
|
"###);
|
|
|
|
// None of the following are valid Rust types.
|
|
syn::parse_str::<Type>("for<'a> dyn Trait<'a>").unwrap_err();
|
|
syn::parse_str::<Type>("dyn for<'a> 'a + Trait").unwrap_err();
|
|
}
|
|
|
|
#[test]
|
|
fn test_trailing_plus() {
|
|
#[rustfmt::skip]
|
|
let tokens = quote!(impl Trait +);
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::ImplTrait {
|
|
bounds: [
|
|
Trait(TraitBound {
|
|
modifier: None,
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Trait",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
}
|
|
"###);
|
|
|
|
#[rustfmt::skip]
|
|
let tokens = quote!(dyn Trait +);
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::TraitObject {
|
|
dyn_token: Some,
|
|
bounds: [
|
|
Trait(TraitBound {
|
|
modifier: None,
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Trait",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
}
|
|
"###);
|
|
|
|
#[rustfmt::skip]
|
|
let tokens = quote!(Trait +);
|
|
snapshot!(tokens as Type, @r###"
|
|
Type::TraitObject {
|
|
bounds: [
|
|
Trait(TraitBound {
|
|
modifier: None,
|
|
path: Path {
|
|
segments: [
|
|
PathSegment {
|
|
ident: "Trait",
|
|
arguments: None,
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
}
|
|
"###);
|
|
}
|