Skip to content

Commit

Permalink
Update to the proc_macro2 crate and rewritten syn
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Jul 6, 2017
1 parent 6721d44 commit 484d177
Show file tree
Hide file tree
Showing 15 changed files with 422 additions and 230 deletions.
5 changes: 0 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,3 @@ members = [
"test_suite",
"test_suite/no_std",
]

[replace]
'syn:0.11.11' = { git = "http://github.com/dtolnay/syn", branch = "master" }
'synom:0.11.3' = { git = "http://github.com/dtolnay/syn", branch = "master" }
'quote:0.3.15' = { git = "http://github.com/dtolnay/quote", branch = "master" }
6 changes: 4 additions & 2 deletions serde_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ name = "serde_derive"
proc-macro = true

[dependencies]
quote = "0.3.8"
quote = { git = 'https://github.com/dtolnay/quote' }
serde_derive_internals = { version = "=0.15.1", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.11", features = ["visit"] }
syn = { git = 'https://github.com/dtolnay/syn', features = ["visit"] }
synom = { git = 'https://github.com/dtolnay/syn', default-features = false }
proc-macro2 = "0.1"
133 changes: 93 additions & 40 deletions serde_derive/src/bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@

use std::collections::HashSet;

use proc_macro2::Term;
use syn::{self, visit};
use synom::span::Span;
use synom::tokens;
use synom::delimited::Delimited;

use internals::ast::Container;
use internals::attr;

macro_rules! path {
($($path:tt)+) => {
syn::parse_path(stringify!($($path)+)).unwrap()
syn::parse_str::<syn::Path>(stringify!($($path)+)).unwrap()
};
}

Expand All @@ -31,11 +35,12 @@ pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
|ty_param| {
syn::TyParam {
default: None,
..ty_param.clone()
..ty_param.into_item().clone()
}
},
)
.collect(),
.collect::<Vec<_>>()
.into(),
..generics.clone()
}
}
Expand All @@ -45,10 +50,12 @@ pub fn with_where_predicates(
predicates: &[syn::WherePredicate],
) -> syn::Generics {
let mut generics = generics.clone();
generics
.where_clause
.predicates
.extend_from_slice(predicates);
for predicate in predicates {
if generics.where_clause.where_token.is_none() {
generics.where_clause.where_token = Some(tokens::Where::default());
}
generics.where_clause.predicates.push_default(predicate.clone());
}
generics
}

Expand All @@ -66,7 +73,12 @@ where
.flat_map(|predicates| predicates.to_vec());

let mut generics = generics.clone();
generics.where_clause.predicates.extend(predicates);
for predicate in predicates {
if generics.where_clause.where_token.is_none() {
generics.where_clause.where_token = Some(tokens::Where::default());
}
generics.where_clause.predicates.push_default(predicate);
}
generics
}

Expand Down Expand Up @@ -101,15 +113,16 @@ where
}
impl visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
if path.segments.len() > 0 {
let seg = *path.segments.get(path.segments.len() - 1).item();
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if !path.global() && path.segments.len() == 1 {
let id = path.segments.get(0).item().ident.clone();
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
Expand All @@ -121,7 +134,7 @@ where
let all_ty_params: HashSet<_> = generics
.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.map(|ty_param| ty_param.item().ident.clone())
.collect();

let relevant_tys = cont.body
Expand All @@ -140,32 +153,41 @@ where
let new_predicates = generics
.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.map(|ty_param| ty_param.item().ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(
|id| {
syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
colon_token: tokens::Colon::default(),
bound_lifetimes: None,
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
bounded_ty: syn::Ty::Path(syn::TyPath {
qself: None,
path: id.into(),
}),
// the bound e.g. Serialize
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
bound_lifetimes: None,
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
].into(),
},
)
},
);

let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates);
for predicate in new_predicates {
if generics.where_clause.where_token.is_none() {
generics.where_clause.where_token = Some(tokens::Where::default());
}
generics.where_clause.predicates.push_default(predicate);
}
generics
}

Expand All @@ -178,22 +200,23 @@ pub fn with_self_bound(
generics
.where_clause
.predicates
.push(
.push_default(
syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
colon_token: tokens::Colon::default(),
bound_lifetimes: None,
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
// the bound e.g. Default
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
bound_lifetimes: None,
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
].into(),
},
),
);
Expand All @@ -203,54 +226,84 @@ pub fn with_self_bound(
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
let mut generics = generics.clone();

for lifetime_def in &mut generics.lifetimes {
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
let lifetime = syn::Lifetime::new(Term::intern(lifetime), Span::default());

for lifetime_def in generics.lifetimes.iter_mut().map(|m| m.into_item()) {
if lifetime_def.colon_token.is_none() {
lifetime_def.colon_token = Some(tokens::Colon::default());
}
lifetime_def
.bounds
.push_default(lifetime.clone());
}

for ty_param in &mut generics.ty_params {
for ty_param in generics.ty_params.iter_mut().map(|i| i.into_item()) {
if ty_param.colon_token.is_none() {
ty_param.colon_token = Some(tokens::Colon::default());
}
ty_param
.bounds
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
.push_default(syn::TyParamBound::Region(lifetime.clone()));
}

if generics.lt_token.is_none() {
generics.lt_token = Some(tokens::Lt::default());
generics.gt_token = Some(tokens::Gt::default());
}

generics
.lifetimes
.push(
.push_default(
syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
lifetime: lifetime,
bounds: Delimited::default(),
colon_token: None,
},
);

if generics.ty_params.len() > 0 && !generics.lifetimes.trailing_delim() {
generics.lifetimes.push_trailing(tokens::Comma::default());
}

generics
}

fn type_of_item(cont: &Container) -> syn::Ty {
syn::Ty::Path(
None,
syn::Path {
global: false,
syn::Ty::Path(syn::TyPath {
qself: None,
path: syn::Path {
leading_colon: None,
segments: vec![
syn::PathSegment {
ident: cont.ident.clone(),
parameters: syn::PathParameters::AngleBracketed(
syn::AngleBracketedParameterData {
gt_token: tokens::Gt::default(),
lt_token: tokens::Lt::default(),
turbofish: None,
lifetimes: cont.generics
.lifetimes
.iter()
.map(|def| def.lifetime.clone())
.collect(),
.map(|def| def.item().lifetime.clone())
.collect::<Vec<_>>()
.into(),
types: cont.generics
.ty_params
.iter()
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
.collect(),
bindings: Vec::new(),
.map(|param| {
syn::Ty::Path(syn::TyPath {
qself: None,
path: param.item().ident.clone().into(),
})
})
.collect::<Vec<_>>()
.into(),
bindings: Delimited::default(),
},
),
},
],
].into(),
},
)
})
}
Loading

0 comments on commit 484d177

Please sign in to comment.