Skip to content

Commit 4957ecc

Browse files
committed
Add test for custom deriving plugins which rely on field attributes
1 parent ede7a6d commit 4957ecc

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// force-host
12+
13+
#![feature(plugin_registrar)]
14+
#![feature(box_syntax)]
15+
#![feature(rustc_private)]
16+
17+
extern crate syntax;
18+
extern crate rustc;
19+
20+
use syntax::ast;
21+
use syntax::attr::AttrMetaMethods;
22+
use syntax::codemap::Span;
23+
use syntax::ext::base::{Decorator, ExtCtxt};
24+
use syntax::ext::build::AstBuilder;
25+
use syntax::ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
26+
use syntax::ext::deriving::generic::{Substructure, Struct, EnumMatching};
27+
use syntax::ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
28+
use syntax::parse::token;
29+
use syntax::ptr::P;
30+
use rustc::plugin::Registry;
31+
32+
#[plugin_registrar]
33+
pub fn plugin_registrar(reg: &mut Registry) {
34+
reg.register_syntax_extension(
35+
token::intern("derive_TotalSum"),
36+
Decorator(box expand));
37+
}
38+
39+
fn expand(cx: &mut ExtCtxt,
40+
span: Span,
41+
mitem: &ast::MetaItem,
42+
item: &ast::Item,
43+
push: &mut FnMut(P<ast::Item>)) {
44+
let trait_def = TraitDef {
45+
span: span,
46+
attributes: vec![],
47+
path: Path::new(vec!["TotalSum"]),
48+
additional_bounds: vec![],
49+
generics: LifetimeBounds::empty(),
50+
associated_types: vec![],
51+
methods: vec![
52+
MethodDef {
53+
name: "total_sum",
54+
generics: LifetimeBounds::empty(),
55+
explicit_self: borrowed_explicit_self(),
56+
args: vec![],
57+
ret_ty: Literal(Path::new_local("isize")),
58+
attributes: vec![],
59+
combine_substructure: combine_substructure(Box::new(totalsum_substructure)),
60+
},
61+
],
62+
};
63+
64+
trait_def.expand(cx, mitem, item, push)
65+
}
66+
67+
// Mostly copied from syntax::ext::deriving::hash
68+
/// Defines how the implementation for `trace()` is to be generated
69+
fn totalsum_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<ast::Expr> {
70+
let fields = match *substr.fields {
71+
Struct(ref fs) | EnumMatching(_, _, ref fs) => fs,
72+
_ => cx.span_bug(trait_span, "impossible substructure")
73+
};
74+
75+
fields.iter().fold(cx.expr_int(trait_span, 0), |acc, ref item| {
76+
if item.attrs.iter().find(|a| a.check_name("ignore")).is_some() {
77+
acc
78+
} else {
79+
cx.expr_binary(item.span, ast::BiAdd, acc,
80+
cx.expr_method_call(item.span,
81+
item.self_.clone(),
82+
substr.method_ident,
83+
Vec::new()))
84+
}
85+
})
86+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:custom_derive_plugin_attr.rs
12+
// ignore-stage1
13+
14+
#![feature(plugin, custom_derive, custom_attribute)]
15+
#![plugin(custom_derive_plugin_attr)]
16+
17+
trait TotalSum {
18+
fn total_sum(&self) -> isize;
19+
}
20+
21+
impl TotalSum for isize {
22+
fn total_sum(&self) -> isize {
23+
*self
24+
}
25+
}
26+
27+
struct Seven;
28+
29+
impl TotalSum for Seven {
30+
fn total_sum(&self) -> isize {
31+
7
32+
}
33+
}
34+
35+
#[derive(TotalSum)]
36+
struct Foo {
37+
seven: Seven,
38+
bar: Bar,
39+
baz: isize,
40+
#[ignore]
41+
nan: NaN,
42+
}
43+
44+
#[derive(TotalSum)]
45+
struct Bar {
46+
quux: isize,
47+
bleh: isize,
48+
#[ignore]
49+
nan: NaN2
50+
}
51+
52+
struct NaN;
53+
54+
impl TotalSum for NaN {
55+
fn total_sum(&self) -> isize {
56+
panic!();
57+
}
58+
}
59+
60+
struct NaN2;
61+
62+
pub fn main() {
63+
let v = Foo {
64+
seven: Seven,
65+
bar: Bar {
66+
quux: 9,
67+
bleh: 3,
68+
nan: NaN2
69+
},
70+
baz: 80,
71+
nan: NaN
72+
};
73+
assert_eq!(v.total_sum(), 99);
74+
}

0 commit comments

Comments
 (0)