Impl parsing
diff --git a/src/expr.rs b/src/expr.rs
index 20e0555..f2f96d0 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -360,6 +360,12 @@
|
expr_mac // must be before expr_path
|
+ expr_break // must be before expr_path
+ |
+ expr_continue // must be before expr_path
+ |
+ expr_ret // must be before expr_path
+ |
expr_box
|
expr_vec
@@ -386,12 +392,6 @@
|
expr_addr_of
|
- expr_break
- |
- expr_continue
- |
- expr_ret
- |
expr_repeat
) >>
many0!(alt!(
diff --git a/src/item.rs b/src/item.rs
index 5df79bb..7b3eac2 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -262,7 +262,8 @@
item_trait
|
item_default_impl
- // TODO: Impl
+ |
+ item_impl
|
item_mac
));
@@ -609,6 +610,159 @@
})
));
+ named!(item_impl -> Item, do_parse!(
+ attrs: many0!(outer_attr) >>
+ unsafety: unsafety >>
+ keyword!("impl") >>
+ generics: generics >>
+ polarity_path: alt!(
+ do_parse!(
+ polarity: impl_polarity >>
+ path: path >>
+ keyword!("for") >>
+ ((polarity, Some(path)))
+ )
+ |
+ epsilon!() => { |_| (ImplPolarity::Positive, None) }
+ ) >>
+ self_ty: ty >>
+ where_clause: where_clause >>
+ punct!("{") >>
+ body: many0!(impl_item) >>
+ punct!("}") >>
+ (Item {
+ ident: "".into(),
+ vis: Visibility::Inherited,
+ attrs: attrs,
+ node: ItemKind::Impl(
+ unsafety,
+ polarity_path.0,
+ Generics {
+ where_clause: where_clause,
+ .. generics
+ },
+ polarity_path.1,
+ Box::new(self_ty),
+ body,
+ ),
+ })
+ ));
+
+ named!(impl_item -> ImplItem, alt!(
+ impl_item_const
+ |
+ impl_item_method
+ |
+ impl_item_type
+ |
+ impl_item_macro
+ ));
+
+ named!(impl_item_const -> ImplItem, do_parse!(
+ attrs: many0!(outer_attr) >>
+ vis: visibility >>
+ defaultness: defaultness >>
+ keyword!("const") >>
+ id: ident >>
+ punct!(":") >>
+ ty: ty >>
+ punct!("=") >>
+ value: expr >>
+ punct!(";") >>
+ (ImplItem {
+ ident: id,
+ vis: vis,
+ defaultness: defaultness,
+ attrs: attrs,
+ node: ImplItemKind::Const(ty, value),
+ })
+ ));
+
+ named!(impl_item_method -> ImplItem, do_parse!(
+ attrs: many0!(outer_attr) >>
+ vis: visibility >>
+ defaultness: defaultness >>
+ constness: constness >>
+ unsafety: unsafety >>
+ abi: option!(preceded!(keyword!("extern"), quoted_string)) >>
+ keyword!("fn") >>
+ name: ident >>
+ generics: generics >>
+ punct!("(") >>
+ inputs: separated_list!(punct!(","), fn_arg) >>
+ punct!(")") >>
+ ret: option!(preceded!(punct!("->"), ty)) >>
+ where_clause: where_clause >>
+ body: block >>
+ (ImplItem {
+ ident: name,
+ vis: vis,
+ defaultness: defaultness,
+ attrs: attrs,
+ node: ImplItemKind::Method(
+ MethodSig {
+ unsafety: unsafety,
+ constness: constness,
+ abi: abi.map(Abi),
+ decl: FnDecl {
+ inputs: inputs,
+ output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
+ },
+ generics: Generics {
+ where_clause: where_clause,
+ .. generics
+ },
+ },
+ body,
+ ),
+ })
+ ));
+
+ named!(impl_item_type -> ImplItem, do_parse!(
+ attrs: many0!(outer_attr) >>
+ vis: visibility >>
+ defaultness: defaultness >>
+ keyword!("type") >>
+ id: ident >>
+ punct!("=") >>
+ ty: ty >>
+ punct!(";") >>
+ (ImplItem {
+ ident: id,
+ vis: vis,
+ defaultness: defaultness,
+ attrs: attrs,
+ node: ImplItemKind::Type(ty),
+ })
+ ));
+
+ named!(impl_item_macro -> ImplItem, do_parse!(
+ attrs: many0!(outer_attr) >>
+ id: ident >>
+ punct!("!") >>
+ body: delimited >>
+ cond!(match body.delim {
+ DelimToken::Paren | DelimToken::Bracket => true,
+ DelimToken::Brace => false,
+ }, punct!(";")) >>
+ (ImplItem {
+ ident: id.clone(),
+ vis: Visibility::Inherited,
+ defaultness: Defaultness::Final,
+ attrs: attrs,
+ node: ImplItemKind::Macro(Mac {
+ path: id.into(),
+ tts: vec![TokenTree::Delimited(body)],
+ }),
+ })
+ ));
+
+ named!(impl_polarity -> ImplPolarity, alt!(
+ punct!("!") => { |_| ImplPolarity::Negative }
+ |
+ epsilon!() => { |_| ImplPolarity::Positive }
+ ));
+
named!(constness -> Constness, alt!(
keyword!("const") => { |_| Constness::Const }
|
@@ -620,6 +774,12 @@
|
epsilon!() => { |_| Unsafety::Normal }
));
+
+ named!(defaultness -> Defaultness, alt!(
+ keyword!("default") => { |_| Defaultness::Default }
+ |
+ epsilon!() => { |_| Defaultness::Final }
+ ));
}
#[cfg(feature = "printing")]
@@ -755,12 +915,26 @@
tokens.append("{");
tokens.append("}");
}
- ItemKind::Impl(_unsafety,
- _polarity,
- ref _generics,
- ref _path,
- ref _ty,
- ref _item) => unimplemented!(),
+ ItemKind::Impl(unsafety,
+ polarity,
+ ref generics,
+ ref path,
+ ref ty,
+ ref items) => {
+ unsafety.to_tokens(tokens);
+ tokens.append("impl");
+ generics.to_tokens(tokens);
+ if let Some(ref path) = *path {
+ polarity.to_tokens(tokens);
+ path.to_tokens(tokens);
+ tokens.append("for");
+ }
+ ty.to_tokens(tokens);
+ generics.where_clause.to_tokens(tokens);
+ tokens.append("{");
+ tokens.append_all(items);
+ tokens.append("}");
+ }
ItemKind::Mac(ref mac) => {
mac.path.to_tokens(tokens);
tokens.append("!");
@@ -839,6 +1013,61 @@
}
}
+ impl ToTokens for ImplItem {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ tokens.append_all(self.attrs.outer());
+ match self.node {
+ ImplItemKind::Const(ref ty, ref expr) => {
+ self.vis.to_tokens(tokens);
+ self.defaultness.to_tokens(tokens);
+ tokens.append("const");
+ self.ident.to_tokens(tokens);
+ tokens.append(":");
+ ty.to_tokens(tokens);
+ tokens.append("=");
+ expr.to_tokens(tokens);
+ tokens.append(";");
+ }
+ ImplItemKind::Method(ref sig, ref block) => {
+ self.vis.to_tokens(tokens);
+ self.defaultness.to_tokens(tokens);
+ sig.unsafety.to_tokens(tokens);
+ sig.abi.to_tokens(tokens);
+ tokens.append("fn");
+ self.ident.to_tokens(tokens);
+ sig.generics.to_tokens(tokens);
+ tokens.append("(");
+ tokens.append_separated(&sig.decl.inputs, ",");
+ tokens.append(")");
+ if let FunctionRetTy::Ty(ref ty) = sig.decl.output {
+ tokens.append("->");
+ ty.to_tokens(tokens);
+ }
+ sig.generics.where_clause.to_tokens(tokens);
+ block.to_tokens(tokens);
+ }
+ ImplItemKind::Type(ref ty) => {
+ self.vis.to_tokens(tokens);
+ self.defaultness.to_tokens(tokens);
+ tokens.append("type");
+ self.ident.to_tokens(tokens);
+ tokens.append("=");
+ ty.to_tokens(tokens);
+ tokens.append(";");
+ }
+ ImplItemKind::Macro(ref mac) => {
+ mac.to_tokens(tokens);
+ match mac.tts.last() {
+ Some(&TokenTree::Delimited(Delimited { delim: DelimToken::Brace, .. })) => {
+ // no semicolon
+ }
+ _ => tokens.append(";"),
+ }
+ }
+ }
+ }
+ }
+
impl ToTokens for FnArg {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
@@ -886,6 +1115,28 @@
}
}
+ impl ToTokens for Defaultness {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ Defaultness::Default => tokens.append("default"),
+ Defaultness::Final => {
+ // nothing
+ }
+ }
+ }
+ }
+
+ impl ToTokens for ImplPolarity {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ ImplPolarity::Negative => tokens.append("!"),
+ ImplPolarity::Positive => {
+ // nothing
+ }
+ }
+ }
+ }
+
impl ToTokens for Abi {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append("extern");
diff --git a/tests/cases/impl.rs b/tests/cases/impl.rs
new file mode 100644
index 0000000..6d4d30c
--- /dev/null
+++ b/tests/cases/impl.rs
@@ -0,0 +1,16 @@
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> FromIterator<T> for Vec<T> {
+ #[inline]
+ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> {}
+}
+
+impl<T> IntoIterator for Vec<T> {
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+}
+
+impl<T: ?Sized> !Sync for *mut T {}
+
+impl [T; 8] {
+ const LEN: usize = 8;
+}
diff --git a/tests/test_round_trip.rs b/tests/test_round_trip.rs
index 9350c32..e197172 100644
--- a/tests/test_round_trip.rs
+++ b/tests/test_round_trip.rs
@@ -80,8 +80,9 @@
fn respan_crate(krate: ast::Crate) -> ast::Crate {
use std::rc::Rc;
- use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ItemKind,
- Mac, MethodSig, TraitItem, TraitItemKind, TyParam};
+ use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
+ ImplItemKind, ItemKind, Mac, MethodSig, TraitItem, TraitItemKind,
+ TyParam};
use syntex_syntax::codemap::{self, Spanned};
use syntex_syntax::fold::{self, Folder};
use syntex_syntax::ptr::P;
@@ -187,6 +188,23 @@
})
}
+ fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
+ let noop = fold::noop_fold_impl_item(i, self).expect_one("");
+ SmallVector::one(ImplItem {
+ node: match noop.node {
+ ImplItemKind::Method(sig, body) => {
+ ImplItemKind::Method(MethodSig {
+ constness: self.fold_spanned(sig.constness),
+ .. sig
+ },
+ body)
+ }
+ node => node,
+ },
+ .. noop
+ })
+ }
+
fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
at.node.id.0 = 0;
fold::noop_fold_attribute(at, self)