Rewrite tokenization with `proc-macro2` tokens
This ended up being a bit larger of a commit than I intended! I imagine that
this'll be one of the larger of the commits working towards #142. The purpose of
this commit is to use an updated version of the `quote` crate which doesn't work
with strings but rather works with tokens form the `proc-macro2` crate. The
`proc-macro2` crate itself is based on the proposed API for `proc_macro` itself,
and will continue to mirror it. The hope is that we'll flip an easy switch
eventually to use compiler tokens, whereas for now we'll stick to string parsing
at the lowest layer.
The largest change here is the addition of span information to the AST. Building
on the previous PRs to refactor the AST this makes it relatively easy from a
user perspective to digest and use the AST still, it's just a few extra fields
on the side. The fallout from this was then quite large throughout the
`printing` feature of the crate. The `parsing`, `fold`, and `visit` features
then followed suit to get updated as well.
This commit also changes the the semantics of the AST somewhat as well.
Previously it was inferred what tokens should be printed, for example if you
have a closure argument `syn` would automatically not print the colon in `a: b`
if the type listed was "infer this type". Now the colon is a separate field and
must be in sync with the type listed as the colon/type will be printed
unconditionally (emitting no output if both are `None`).
diff --git a/tests/test_expr.rs b/tests/test_expr.rs
index 1fe0180..6216191 100644
--- a/tests/test_expr.rs
+++ b/tests/test_expr.rs
@@ -1,3 +1,5 @@
+#![cfg(feature = "extra-traits")]
+
extern crate syn;
use syn::*;
@@ -98,7 +100,7 @@
});
assert_let!(Stmt::Local(ref local) = block.stmts[2]; {
- assert_let!(Pat::Ident(BindingMode::ByValue(Mutability::Mutable), ref ident, None) = *local.pat; {
+ assert_let!(Pat::Ident(PatIdent { mode: BindingMode::ByValue(Mutability::Mutable(_)), ref ident, .. }) = *local.pat; {
assert_eq!(ident, "catch");
});
});
@@ -111,8 +113,8 @@
});
});
- assert_let!(Stmt::Semi(ref expr) = block.stmts[5]; {
- assert_let!(Expr { node: ExprKind::Assign(ExprAssign { ref left, ref right }), .. } = **expr; {
+ assert_let!(Stmt::Semi(ref expr, _) = block.stmts[5]; {
+ assert_let!(Expr { node: ExprKind::Assign(ExprAssign { ref left, ref right, .. }), .. } = **expr; {
assert_let!(Expr { node: ExprKind::Path(ExprPath { qself: None, ref path }), .. } = **left; {
assert_eq!(*path, "catch".into());
});
@@ -125,7 +127,7 @@
});
});
- assert_let!(Stmt::Semi(ref expr) = block.stmts[7]; {
+ assert_let!(Stmt::Semi(ref expr, _) = block.stmts[7]; {
assert_let!(Expr { node: ExprKind::Match(ExprMatch { ref expr, .. }), .. } = **expr; {
assert_let!(Expr { node: ExprKind::Path(ExprPath { qself: None, ref path }), .. } = **expr; {
assert_eq!(*path, "catch".into());
diff --git a/tests/test_generics.rs b/tests/test_generics.rs
index 92ae9e9..e18d2ef 100644
--- a/tests/test_generics.rs
+++ b/tests/test_generics.rs
@@ -9,47 +9,68 @@
#[test]
fn test_split_for_impl() {
// <'a, 'b: 'a, #[may_dangle] T: 'a = ()> where T: Debug
- let generics = Generics {
- lifetimes: vec![LifetimeDef {
- attrs: Vec::new(),
- lifetime: Lifetime::new("'a"),
- bounds: Vec::new(),
- },
- LifetimeDef {
- attrs: Vec::new(),
- lifetime: Lifetime::new("'b"),
- bounds: vec![Lifetime::new("'a")],
- }],
- ty_params: vec![TyParam {
- attrs: vec![Attribute {
- style: AttrStyle::Outer,
- path: "may_dangle".into(),
- tts: vec![],
- is_sugared_doc: false,
- }],
- ident: Ident::new("T"),
- bounds: vec![TyParamBound::Region(Lifetime::new("'a"))],
- default: Some(TyTup { tys: Vec::new() }.into()),
- }],
+ let mut generics = Generics {
+ gt_token: Some(Default::default()),
+ lt_token: Some(Default::default()),
+ lifetimes: vec![
+ LifetimeDef {
+ attrs: Default::default(),
+ lifetime: Lifetime::new("'a"),
+ bounds: Default::default(),
+ colon_token: None,
+ },
+ LifetimeDef {
+ attrs: Default::default(),
+ lifetime: Lifetime::new("'b"),
+ bounds: vec![Lifetime::new("'a")].into(),
+ colon_token: Some(tokens::Colon::default()),
+ },
+ ].into(),
+ ty_params: vec![
+ TyParam {
+ attrs: vec![Attribute {
+ bracket_token: Default::default(),
+ pound_token: Default::default(),
+ style: AttrStyle::Outer,
+ path: "may_dangle".into(),
+ tts: vec![],
+ is_sugared_doc: false,
+ }],
+ ident: "T".into(),
+ bounds: vec![TyParamBound::Region(Lifetime::new("'a"))].into(),
+ default: Some(TyTup {
+ tys: Default::default(),
+ lone_comma: None,
+ paren_token: Default::default(),
+ }.into()),
+ colon_token: Some(Default::default()),
+ eq_token: Default::default(),
+ },
+ ].into(),
where_clause: WhereClause {
- predicates: vec![WherePredicate::BoundPredicate(WhereBoundPredicate {
- bound_lifetimes: Vec::new(),
- bounded_ty: TyPath {
- qself: None,
- path: "T".into(),
- }.into(),
- bounds: vec![
+ where_token: Some(Default::default()),
+ predicates: vec![
+ WherePredicate::BoundPredicate(WhereBoundPredicate {
+ bound_lifetimes: None,
+ colon_token: Default::default(),
+ bounded_ty: TyPath {
+ qself: None,
+ path: "T".into(),
+ }.into(),
+ bounds: vec![
TyParamBound::Trait(
PolyTraitRef {
- bound_lifetimes: Vec::new(),
+ bound_lifetimes: None,
trait_ref: "Debug".into(),
},
TraitBoundModifier::None,
),
- ],
- })],
+ ].into(),
+ })
+ ].into(),
},
};
+ generics.lifetimes.push_trailing(Default::default());
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let tokens = quote! {
@@ -72,21 +93,23 @@
fn test_ty_param_bound() {
let tokens = quote!('a);
let expected = TyParamBound::Region(Lifetime::new("'a"));
- assert_eq!(expected, parse_ty_param_bound(tokens.as_str()).unwrap());
+ assert_eq!(expected, parse_ty_param_bound(&tokens.to_string()).unwrap());
let tokens = quote!(Debug);
- let expected = TyParamBound::Trait(PolyTraitRef {
- bound_lifetimes: Vec::new(),
- trait_ref: "Debug".into(),
- },
- TraitBoundModifier::None);
- assert_eq!(expected, parse_ty_param_bound(tokens.as_str()).unwrap());
+ let expected = TyParamBound::Trait(
+ PolyTraitRef {
+ bound_lifetimes: None,
+ trait_ref: "Debug".into(),
+ },
+ TraitBoundModifier::None);
+ assert_eq!(expected, parse_ty_param_bound(&tokens.to_string()).unwrap());
let tokens = quote!(?Sized);
- let expected = TyParamBound::Trait(PolyTraitRef {
- bound_lifetimes: Vec::new(),
- trait_ref: "Sized".into(),
- },
- TraitBoundModifier::Maybe);
- assert_eq!(expected, parse_ty_param_bound(tokens.as_str()).unwrap());
+ let expected = TyParamBound::Trait(
+ PolyTraitRef {
+ bound_lifetimes: None,
+ trait_ref: "Sized".into(),
+ },
+ TraitBoundModifier::Maybe(Default::default()));
+ assert_eq!(expected, parse_ty_param_bound(&tokens.to_string()).unwrap());
}
diff --git a/tests/test_macro_input.rs b/tests/test_macro_input.rs
index 653fbe2..4237060 100644
--- a/tests/test_macro_input.rs
+++ b/tests/test_macro_input.rs
@@ -5,7 +5,39 @@
#![cfg(feature = "extra-traits")]
extern crate syn;
+extern crate proc_macro2;
+
use syn::*;
+use proc_macro2::{TokenKind, OpKind, Delimiter, Literal};
+use proc_macro2::Delimiter::{Parenthesis, Brace};
+
+fn op(c: char) -> TokenTree {
+ TokenTree(proc_macro2::TokenTree {
+ span: Default::default(),
+ kind: TokenKind::Op(c, OpKind::Alone),
+ })
+}
+
+fn lit<T: Into<Literal>>(t: T) -> TokenTree {
+ TokenTree(proc_macro2::TokenTree {
+ span: Default::default(),
+ kind: TokenKind::Literal(t.into()),
+ })
+}
+
+fn word(sym: &str) -> TokenTree {
+ TokenTree(proc_macro2::TokenTree {
+ span: Default::default(),
+ kind: TokenKind::Word(sym.into()),
+ })
+}
+
+fn delimited(delim: Delimiter, tokens: Vec<TokenTree>) -> TokenTree {
+ TokenTree(proc_macro2::TokenTree {
+ span: Default::default(),
+ kind: TokenKind::Sequence(delim, tokens.into_iter().map(|t| t.0).collect()),
+ })
+}
#[test]
fn test_unit() {
@@ -13,10 +45,14 @@
let expected = MacroInput {
ident: "Unit".into(),
- vis: Visibility::Inherited,
+ vis: Visibility::Inherited(VisInherited {}),
attrs: Vec::new(),
generics: Generics::default(),
- body: Body::Struct(VariantData::Unit),
+ body: Body::Struct(BodyStruct {
+ semi_token: Some(Default::default()),
+ struct_token: Default::default(),
+ data: VariantData::Unit,
+ }),
};
assert_eq!(expected, parse_macro_input(raw).unwrap());
@@ -28,63 +64,80 @@
#[derive(Debug, Clone)]
pub struct Item {
pub ident: Ident,
- pub attrs: Vec<Attribute>,
+ pub attrs: Vec<Attribute>
}
";
let expected = MacroInput {
ident: "Item".into(),
- vis: Visibility::Public,
+ vis: Visibility::Public(VisPublic {
+ pub_token: Default::default(),
+ }),
attrs: vec![Attribute {
+ bracket_token: Default::default(),
+ pound_token: Default::default(),
style: AttrStyle::Outer,
path: "derive".into(),
tts: vec![
- TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![
- TokenTree::Token(Token::Ident("Debug".into())),
- TokenTree::Token(Token::Comma),
- TokenTree::Token(Token::Ident("Clone".into())),
- ]})
+ delimited(Parenthesis, vec![
+ word("Debug"),
+ op(','),
+ word("Clone"),
+ ]),
],
is_sugared_doc: false,
}],
generics: Generics::default(),
- body: Body::Struct(VariantData::Struct(vec![
- Field {
- ident: Some("ident".into()),
- vis: Visibility::Public,
- attrs: Vec::new(),
- ty: TyPath {
- qself: None,
- path: "Ident".into(),
- }.into(),
- },
- Field {
- ident: Some("attrs".into()),
- vis: Visibility::Public,
- attrs: Vec::new(),
- ty: TyPath {
- qself: None,
- path: Path {
- global: false,
- segments: vec![
- PathSegment {
- ident: "Vec".into(),
- parameters: PathParameters::AngleBracketed(
- AngleBracketedParameterData {
- lifetimes: Vec::new(),
- types: vec![TyPath {
- qself: None,
- path: "Attribute".into(),
- }.into()],
- bindings: Vec::new(),
- },
- ),
- }
- ],
- },
- }.into(),
- },
- ]))
+ body: Body::Struct(BodyStruct {
+ semi_token: None,
+ struct_token: Default::default(),
+ data: VariantData::Struct(vec![
+ Field {
+ ident: Some("ident".into()),
+ colon_token: Some(Default::default()),
+ vis: Visibility::Public(VisPublic {
+ pub_token: Default::default(),
+ }),
+ attrs: Vec::new(),
+ ty: TyPath {
+ qself: None,
+ path: "Ident".into(),
+ }.into(),
+ },
+ Field {
+ ident: Some("attrs".into()),
+ colon_token: Some(Default::default()),
+ vis: Visibility::Public(VisPublic {
+ pub_token: Default::default(),
+ }),
+ attrs: Vec::new(),
+ ty: TyPath {
+ qself: None,
+ path: Path {
+ leading_colon: None,
+ global: false,
+ segments: vec![
+ PathSegment {
+ ident: "Vec".into(),
+ parameters: PathParameters::AngleBracketed(
+ AngleBracketedParameterData {
+ gt_token: Some(Default::default()),
+ lt_token: Some(Default::default()),
+ lifetimes: Default::default(),
+ types: vec![Ty::from(TyPath {
+ qself: None,
+ path: "Attribute".into(),
+ })].into(),
+ bindings: Default::default(),
+ },
+ ),
+ }
+ ].into(),
+ },
+ }.into(),
+ },
+ ].into(), Default::default()),
+ }),
};
let actual = parse_macro_input(raw).unwrap();
@@ -93,10 +146,11 @@
let expected_meta_item: MetaItem = MetaItemList {
ident: "derive".into(),
+ paren_token: Default::default(),
nested: vec![
NestedMetaItem::MetaItem(MetaItem::Word("Debug".into())),
NestedMetaItem::MetaItem(MetaItem::Word("Clone".into())),
- ],
+ ].into(),
}.into();
assert_eq!(expected_meta_item, actual.attrs[0].meta_item().unwrap());
@@ -115,27 +169,30 @@
// Smuggling data into a proc_macro_derive,
// in the style of https://github.com/dtolnay/proc-macro-hack
- ProcMacroHack = (0, "data").0,
+ ProcMacroHack = (0, "data").0
}
"#;
let expected = MacroInput {
ident: "Result".into(),
- vis: Visibility::Public,
+ vis: Visibility::Public(VisPublic {
+ pub_token: Default::default(),
+ }),
attrs: vec![
Attribute {
+ bracket_token: Default::default(),
+ pound_token: Default::default(),
style: AttrStyle::Outer,
path: "doc".into(),
tts: vec![
- TokenTree::Token(Token::Eq),
- TokenTree::Token(Token::Literal(Lit::Str(
- "/// See the std::result module documentation for details.".into(),
- StrStyle::Cooked,
- ))),
+ op('='),
+ lit(Literal::doccomment("/// See the std::result module documentation for details.")),
],
is_sugared_doc: true,
},
Attribute {
+ bracket_token: Default::default(),
+ pound_token: Default::default(),
style: AttrStyle::Outer,
path: "must_use".into(),
tts: vec![],
@@ -143,81 +200,114 @@
},
],
generics: Generics {
- lifetimes: Vec::new(),
- ty_params: vec![TyParam {
- attrs: Vec::new(),
- ident: "T".into(),
- bounds: Vec::new(),
- default: None,
- },
- TyParam {
- attrs: Vec::new(),
- ident: "E".into(),
- bounds: Vec::new(),
- default: None,
- }],
- where_clause: WhereClause { predicates: Vec::new() },
- },
- body: Body::Enum(vec![
- Variant {
- ident: "Ok".into(),
- attrs: Vec::new(),
- data: VariantData::Tuple(vec![
- Field {
- ident: None,
- vis: Visibility::Inherited,
- attrs: Vec::new(),
- ty: TyPath { qself: None, path: "T".into() }.into(),
- },
- ]),
- discriminant: None,
- },
- Variant {
- ident: "Err".into(),
- attrs: Vec::new(),
- data: VariantData::Tuple(vec![
- Field {
- ident: None,
- vis: Visibility::Inherited,
- attrs: Vec::new(),
- ty: TyPath { qself: None, path: "E".into() }.into(),
- },
- ]),
- discriminant: None,
- },
- Variant {
- ident: "Surprise".into(),
- attrs: Vec::new(),
- data: VariantData::Unit,
- discriminant: Some(ConstExpr::Lit(Lit::Int(0, IntTy::Isize))),
- },
- Variant {
- ident: "ProcMacroHack".into(),
- attrs: Vec::new(),
- data: VariantData::Unit,
- discriminant: Some(ConstExpr::Other(Expr {
- node: ExprTupField {
- expr: Box::new(Expr {
- node: ExprTup {
- args: vec![
- Expr {
- node: ExprKind::Lit(Lit::Int(0, IntTy::Unsuffixed)),
- attrs: Vec::new(),
- },
- Expr {
- node: ExprKind::Lit(Lit::Str("data".into(), StrStyle::Cooked)),
- attrs: Vec::new(),
- },
- ],
- }.into(),
- attrs: Vec::new(),
- }),
- field: 0
- }.into(),
+ lifetimes: Default::default(),
+ lt_token: Some(Default::default()),
+ gt_token: Some(Default::default()),
+ ty_params: vec![
+ TyParam {
attrs: Vec::new(),
- })),
- },
- ]),
+ ident: "T".into(),
+ bounds: Default::default(),
+ default: None,
+ colon_token: None,
+ eq_token: None,
+ },
+ TyParam {
+ attrs: Vec::new(),
+ ident: "E".into(),
+ bounds: Default::default(),
+ colon_token: None,
+ eq_token: None,
+ default: None,
+ },
+ ].into(),
+ where_clause: WhereClause::default(),
+ },
+ body: Body::Enum(BodyEnum {
+ variants: vec![
+ Variant {
+ ident: "Ok".into(),
+ attrs: Vec::new(),
+ eq_token: None,
+ data: VariantData::Tuple(vec![
+ Field {
+ colon_token: None,
+ ident: None,
+ vis: Visibility::Inherited(VisInherited {}),
+ attrs: Vec::new(),
+ ty: TyPath { qself: None, path: "T".into() }.into(),
+ },
+ ].into(), Default::default()),
+ discriminant: None,
+ },
+ Variant {
+ ident: "Err".into(),
+ attrs: Vec::new(),
+ eq_token: None,
+ data: VariantData::Tuple(vec![
+ Field {
+ ident: None,
+ colon_token: None,
+ vis: Visibility::Inherited(VisInherited {}),
+ attrs: Vec::new(),
+ ty: TyPath { qself: None, path: "E".into() }.into(),
+ },
+ ].into(), Default::default()),
+ discriminant: None,
+ },
+ Variant {
+ ident: "Surprise".into(),
+ attrs: Vec::new(),
+ data: VariantData::Unit,
+ eq_token: Some(Default::default()),
+ discriminant: Some(ConstExpr::Lit(Lit {
+ value: LitKind::Other(0isize.into()),
+ span: Default::default(),
+ })),
+ },
+ Variant {
+ ident: "ProcMacroHack".into(),
+ attrs: Vec::new(),
+ data: VariantData::Unit,
+ eq_token: Some(Default::default()),
+ discriminant: Some(ConstExpr::Other(Expr {
+ node: ExprTupField {
+ expr: Box::new(Expr {
+ node: ExprTup {
+ lone_comma: None,
+ paren_token: Default::default(),
+ args: vec![
+ Expr {
+ node: ExprKind::Lit(Lit {
+ value: LitKind::Other(Literal::integer("0")),
+ span: Default::default(),
+ }),
+ attrs: Vec::new(),
+ },
+ Expr {
+ node: ExprKind::Lit(Lit {
+ value: LitKind::Other("data".into()),
+ span: Default::default(),
+ }),
+ attrs: Vec::new(),
+ },
+ ].into(),
+ }.into(),
+ attrs: Vec::new(),
+ }),
+ dot_token: Default::default(),
+ field: Lit {
+ value: LitKind::Other(Literal::integer("0")),
+ span: Default::default(),
+ },
+ }.into(),
+ attrs: Vec::new(),
+ })),
+ },
+ ].into(),
+ brace_token: Default::default(),
+ enum_token: Default::default(),
+ }),
};
let actual = parse_macro_input(raw).unwrap();
@@ -227,10 +317,11 @@
let expected_meta_items = vec![
MetaNameValue {
ident: "doc".into(),
- lit: Lit::Str(
- "/// See the std::result module documentation for details.".into(),
- StrStyle::Cooked,
- ),
+ eq_token: Default::default(),
+ lit: Lit {
+ value: LitKind::Other(Literal::doccomment("/// See the std::result module documentation for details.")),
+ span: Default::default(),
+ },
}.into(),
MetaItem::Word("must_use".into()),
];
@@ -250,30 +341,43 @@
let expected = MacroInput {
ident: "Dummy".into(),
- vis: Visibility::Inherited,
+ vis: Visibility::Inherited(VisInherited {}),
attrs: vec![Attribute {
+ bracket_token: Default::default(),
+ pound_token: Default::default(),
style: AttrStyle::Outer,
- path: Path { global: true, segments: vec!["attr_args".into(), "identity".into()] },
+ path: Path {
+ global: true,
+ leading_colon: Some(Default::default()),
+ segments: vec![
+ PathSegment::from("attr_args"),
+ PathSegment::from("identity"),
+ ].into(),
+ },
tts: vec![
- TokenTree::Token(Token::Ident("fn".into())),
- TokenTree::Token(Token::Ident("main".into())),
- TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![] }),
- TokenTree::Delimited(Delimited { delim: DelimToken::Brace, tts: vec![
- TokenTree::Token(Token::Ident("assert_eq".into())),
- TokenTree::Token(Token::Not),
- TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![
- TokenTree::Token(Token::Ident("foo".into())),
- TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![] }),
- TokenTree::Token(Token::Comma),
- TokenTree::Token(Token::Literal(Lit::Str("Hello, world!".into(), StrStyle::Cooked))),
- ]}),
- TokenTree::Token(Token::Semi),
- ]})
+ word("fn"),
+ word("main"),
+ delimited(Parenthesis, vec![]),
+ delimited(Brace, vec![
+ word("assert_eq"),
+ op('!'),
+ delimited(Parenthesis, vec![
+ word("foo"),
+ delimited(Parenthesis, vec![]),
+ op(','),
+ lit("Hello, world!"),
+ ]),
+ op(';'),
+ ]),
],
is_sugared_doc: false,
}],
generics: Generics::default(),
- body: Body::Struct(VariantData::Unit),
+ body: Body::Struct(BodyStruct {
+ data: VariantData::Unit,
+ semi_token: Some(Default::default()),
+ struct_token: Default::default(),
+ }),
};
let actual = parse_macro_input(raw).unwrap();
@@ -292,19 +396,31 @@
let expected = MacroInput {
ident: "S".into(),
- vis: Visibility::Inherited,
+ vis: Visibility::Inherited(VisInherited {}),
attrs: vec![Attribute {
+ bracket_token: Default::default(),
+ pound_token: Default::default(),
style: AttrStyle::Outer,
- path: Path { global: false, segments: vec!["inert".into()] },
+ path: Path {
+ global: false,
+ leading_colon: None,
+ segments: vec![
+ PathSegment::from("inert"),
+ ].into(),
+ },
tts: vec![
- TokenTree::Token(Token::Lt),
- TokenTree::Token(Token::Ident("T".into())),
- TokenTree::Token(Token::Gt),
+ op('<'),
+ word("T"),
+ op('>'),
],
is_sugared_doc: false,
}],
generics: Generics::default(),
- body: Body::Struct(VariantData::Unit),
+ body: Body::Struct(BodyStruct {
+ data: VariantData::Unit,
+ semi_token: Some(Default::default()),
+ struct_token: Default::default(),
+ }),
};
let actual = parse_macro_input(raw).unwrap();
@@ -323,15 +439,28 @@
let expected = MacroInput {
ident: "S".into(),
- vis: Visibility::Inherited,
+ vis: Visibility::Inherited(VisInherited {}),
attrs: vec![Attribute {
+ bracket_token: Default::default(),
+ pound_token: Default::default(),
style: AttrStyle::Outer,
- path: Path { global: false, segments: vec!["foo".into(), "self".into()] },
+ path: Path {
+ global: false,
+ leading_colon: None,
+ segments: vec![
+ PathSegment::from("foo"),
+ PathSegment::from("self"),
+ ].into(),
+ },
tts: vec![],
is_sugared_doc: false,
}],
generics: Generics::default(),
- body: Body::Struct(VariantData::Unit),
+ body: Body::Struct(BodyStruct {
+ data: VariantData::Unit,
+ semi_token: Some(Default::default()),
+ struct_token: Default::default(),
+ }),
};
let actual = parse_macro_input(raw).unwrap();
@@ -350,15 +479,40 @@
let expected = MacroInput {
ident: "Z".into(),
- vis: Visibility::Restricted(Box::new("m".into())),
+ vis: Visibility::Restricted(VisRestricted {
+ path: Box::new("m".into()),
+ in_token: Some(Default::default()),
+ paren_token: Default::default(),
+ pub_token: Default::default(),
+ }),
attrs: vec![],
generics: Generics::default(),
- body: Body::Struct(VariantData::Tuple(vec![Field {
- ident: None,
- vis: Visibility::Restricted(Box::new(Path { global: false, segments: vec!["m".into(), "n".into()] })),
- attrs: vec![],
- ty: TyPath { qself: None, path: "u8".into() }.into(),
- }])),
+ body: Body::Struct(BodyStruct {
+ data: VariantData::Tuple(vec![Field {
+ ident: None,
+ vis: Visibility::Restricted(VisRestricted {
+ path: Box::new(Path {
+ global: false,
+ leading_colon: None,
+ segments: vec![
+ PathSegment::from("m"),
+ PathSegment::from("n"),
+ ].into(),
+ }),
+ in_token: Some(Default::default()),
+ paren_token: Default::default(),
+ pub_token: Default::default(),
+ }),
+ colon_token: None,
+ attrs: vec![],
+ ty: TyPath {
+ qself: None,
+ path: "u8".into(),
+ }.into(),
+ }].into(), Default::default()),
+ semi_token: Some(Default::default()),
+ struct_token: Default::default(),
+ }),
};
let actual = parse_macro_input(raw).unwrap();
@@ -374,10 +528,18 @@
let expected = MacroInput {
ident: "S".into(),
- vis: Visibility::Crate,
+ vis: Visibility::Crate(VisCrate {
+ pub_token: Default::default(),
+ crate_token: Default::default(),
+ paren_token: Default::default(),
+ }),
attrs: vec![],
generics: Generics::default(),
- body: Body::Struct(VariantData::Unit),
+ body: Body::Struct(BodyStruct {
+ semi_token: Some(Default::default()),
+ struct_token: Default::default(),
+ data: VariantData::Unit,
+ }),
};
let actual = parse_macro_input(raw).unwrap();
@@ -393,10 +555,19 @@
let expected = MacroInput {
ident: "S".into(),
- vis: Visibility::Restricted(Box::new("super".into())),
+ vis: Visibility::Restricted(VisRestricted {
+ path: Box::new("super".into()),
+ in_token: None,
+ paren_token: Default::default(),
+ pub_token: Default::default(),
+ }),
attrs: vec![],
generics: Generics::default(),
- body: Body::Struct(VariantData::Unit),
+ body: Body::Struct(BodyStruct {
+ semi_token: Some(Default::default()),
+ struct_token: Default::default(),
+ data: VariantData::Unit,
+ }),
};
let actual = parse_macro_input(raw).unwrap();
@@ -412,10 +583,19 @@
let expected = MacroInput {
ident: "S".into(),
- vis: Visibility::Restricted(Box::new("super".into())),
+ vis: Visibility::Restricted(VisRestricted {
+ path: Box::new("super".into()),
+ in_token: Some(Default::default()),
+ paren_token: Default::default(),
+ pub_token: Default::default(),
+ }),
attrs: vec![],
generics: Generics::default(),
- body: Body::Struct(VariantData::Unit),
+ body: Body::Struct(BodyStruct {
+ semi_token: Some(Default::default()),
+ struct_token: Default::default(),
+ data: VariantData::Unit,
+ }),
};
let actual = parse_macro_input(raw).unwrap();
diff --git a/tests/test_meta_item.rs b/tests/test_meta_item.rs
index 72cec3a..acf1710 100644
--- a/tests/test_meta_item.rs
+++ b/tests/test_meta_item.rs
@@ -1,7 +1,17 @@
#![cfg(feature = "extra-traits")]
extern crate syn;
+extern crate proc_macro2;
+
use syn::*;
+use proc_macro2::Literal;
+
+fn lit<T: Into<Literal>>(t: T) -> Lit {
+ Lit {
+ value: LitKind::Other(t.into()),
+ span: Default::default(),
+ }
+}
#[test]
fn test_meta_item_word() {
@@ -12,7 +22,8 @@
fn test_meta_item_name_value() {
run_test("#[foo = 5]", MetaNameValue {
ident: "foo".into(),
- lit: Lit::Int(5, IntTy::Unsuffixed),
+ eq_token: Default::default(),
+ lit: lit(Literal::integer("5")),
})
}
@@ -20,9 +31,10 @@
fn test_meta_item_list_lit() {
run_test("#[foo(5)]", MetaItemList {
ident: "foo".into(),
+ paren_token: Default::default(),
nested: vec![
- NestedMetaItem::Literal(Lit::Int(5, IntTy::Unsuffixed)),
- ],
+ NestedMetaItem::Literal(lit(Literal::integer("5"))),
+ ].into(),
})
}
@@ -30,9 +42,10 @@
fn test_meta_item_list_word() {
run_test("#[foo(bar)]", MetaItemList {
ident: "foo".into(),
+ paren_token: Default::default(),
nested: vec![
NestedMetaItem::MetaItem(MetaItem::Word("bar".into())),
- ],
+ ].into(),
})
}
@@ -40,12 +53,14 @@
fn test_meta_item_list_name_value() {
run_test("#[foo(bar = 5)]", MetaItemList {
ident: "foo".into(),
+ paren_token: Default::default(),
nested: vec![
NestedMetaItem::MetaItem(MetaNameValue {
ident: "bar".into(),
- lit: Lit::Int(5, IntTy::Unsuffixed),
+ eq_token: Default::default(),
+ lit: lit(Literal::integer("5"))
}.into()),
- ],
+ ].into(),
})
}
@@ -53,23 +68,27 @@
fn test_meta_item_multiple() {
run_test("#[foo(word, name = 5, list(name2 = 6), word2)]", MetaItemList {
ident: "foo".into(),
+ paren_token: Default::default(),
nested: vec![
NestedMetaItem::MetaItem(MetaItem::Word("word".into())),
NestedMetaItem::MetaItem(MetaNameValue {
ident: "name".into(),
- lit: Lit::Int(5, IntTy::Unsuffixed),
+ eq_token: Default::default(),
+ lit: lit(Literal::integer("5")),
}.into()),
NestedMetaItem::MetaItem(MetaItemList {
ident: "list".into(),
+ paren_token: Default::default(),
nested: vec![
NestedMetaItem::MetaItem(MetaNameValue {
ident: "name2".into(),
- lit: Lit::Int(6, IntTy::Unsuffixed),
+ eq_token: Default::default(),
+ lit: lit(Literal::integer("6")),
}.into())
- ],
+ ].into(),
}.into()),
NestedMetaItem::MetaItem(MetaItem::Word("word2".into())),
- ],
+ ].into(),
})
}
diff --git a/tests/test_token_trees.rs b/tests/test_token_trees.rs
index 33dbdda..3616a70 100644
--- a/tests/test_token_trees.rs
+++ b/tests/test_token_trees.rs
@@ -1,9 +1,32 @@
#![cfg(feature = "extra-traits")]
extern crate syn;
-use syn::TokenTree::{self, Token};
-use syn::DelimToken::*;
-use syn::Token::*;
+extern crate proc_macro2;
+
+use syn::TokenTree;
+use proc_macro2::{TokenKind, OpKind, Delimiter};
+use proc_macro2::Delimiter::*;
+
+fn op(c: char) -> TokenTree {
+ TokenTree(proc_macro2::TokenTree {
+ span: Default::default(),
+ kind: TokenKind::Op(c, OpKind::Alone),
+ })
+}
+
+fn delimited(delim: Delimiter, tokens: Vec<TokenTree>) -> TokenTree {
+ TokenTree(proc_macro2::TokenTree {
+ span: Default::default(),
+ kind: TokenKind::Sequence(delim, tokens.into_iter().map(|t| t.0).collect()),
+ })
+}
+
+fn word(sym: &str) -> TokenTree {
+ TokenTree(proc_macro2::TokenTree {
+ span: Default::default(),
+ kind: TokenKind::Word(sym.into()),
+ })
+}
#[test]
fn test_struct() {
@@ -15,43 +38,39 @@
}
";
- let expected =
- vec![Token(Pound),
- delimited(Bracket,
- vec![ident("derive"),
- delimited(Paren, vec![ident("Debug"), Token(Comma), ident("Clone")])]),
- ident("pub"),
- ident("struct"),
- ident("Item"),
- delimited(Brace,
- vec![ident("pub"),
- ident("ident"),
- Token(Colon),
- ident("Ident"),
- Token(Comma),
+ let expected = vec![
+ op('#'),
+ delimited(Bracket, vec![
+ word("derive"),
+ delimited(Parenthesis, vec![
+ word("Debug"),
+ op(','),
+ word("Clone"),
+ ]),
+ ]),
+ word("pub"),
+ word("struct"),
+ word("Item"),
+ delimited(Brace, vec![
+ word("pub"),
+ word("ident"),
+ op(':'),
+ word("Ident"),
+ op(','),
- ident("pub"),
- ident("attrs"),
- Token(Colon),
- ident("Vec"),
- Token(Lt),
- ident("Attribute"),
- Token(Gt),
- Token(Comma)])];
+ word("pub"),
+ word("attrs"),
+ op(':'),
+ word("Vec"),
+ op('<'),
+ word("Attribute"),
+ op('>'),
+ op(','),
+ ],
+ )];
let result = syn::parse_token_trees(raw).unwrap();
if result != expected {
panic!("{:#?}\n!=\n{:#?}", result, expected);
}
}
-
-fn delimited(delim: syn::DelimToken, tts: Vec<TokenTree>) -> TokenTree {
- TokenTree::Delimited(syn::Delimited {
- delim: delim,
- tts: tts,
- })
-}
-
-fn ident(s: &str) -> TokenTree {
- TokenTree::Token(Ident(syn::Ident::new(s)))
-}