1 // Copyright 2014 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.
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.
12 use ast
::{MetaItem, Expr,}
;
14 use ext
::base
::{ExtCtxt, Annotatable}
;
15 use ext
::build
::AstBuilder
;
16 use ext
::deriving
::generic
::*;
17 use ext
::deriving
::generic
::ty
::*;
21 pub fn expand_deriving_show(cx
: &mut ExtCtxt
,
25 push
: &mut FnMut(Annotatable
))
27 // &mut ::std::fmt::Formatter
28 let fmtr
= Ptr(Box
::new(Literal(path_std
!(cx
, core
::fmt
::Formatter
))),
29 Borrowed(None
, ast
::MutMutable
));
31 let trait_def
= TraitDef
{
33 attributes
: Vec
::new(),
34 path
: path_std
!(cx
, core
::fmt
::Debug
),
35 additional_bounds
: Vec
::new(),
36 generics
: LifetimeBounds
::empty(),
40 generics
: LifetimeBounds
::empty(),
41 explicit_self
: borrowed_explicit_self(),
43 ret_ty
: Literal(path_std
!(cx
, core
::fmt
::Result
)),
44 attributes
: Vec
::new(),
45 combine_substructure
: combine_substructure(Box
::new(|a
, b
, c
| {
46 show_substructure(a
, b
, c
)
50 associated_types
: Vec
::new(),
52 trait_def
.expand(cx
, mitem
, &item
, push
)
55 /// We use the debug builders to do the heavy lifting here
56 fn show_substructure(cx
: &mut ExtCtxt
, span
: Span
,
57 substr
: &Substructure
) -> P
<Expr
> {
58 // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
59 // or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
60 // based on the "shape".
61 let name
= match *substr
.fields
{
62 Struct(_
) => substr
.type_ident
,
63 EnumMatching(_
, v
, _
) => v
.node
.name
,
64 EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => {
65 cx
.span_bug(span
, "nonsensical .fields in `#[derive(Debug)]`")
69 // We want to make sure we have the expn_id set so that we can use unstable methods
70 let span
= Span { expn_id: cx.backtrace(), .. span }
;
71 let name
= cx
.expr_lit(span
, ast
::Lit_
::LitStr(token
::get_ident(name
),
72 ast
::StrStyle
::CookedStr
));
73 let mut expr
= substr
.nonself_args
[0].clone();
75 match *substr
.fields
{
76 Struct(ref fields
) | EnumMatching(_
, _
, ref fields
) => {
77 if fields
.is_empty() || fields
[0].name
.is_none() {
78 // tuple struct/"normal" variant
79 expr
= cx
.expr_method_call(span
,
81 token
::str_to_ident("debug_tuple"),
85 expr
= cx
.expr_method_call(span
,
87 token
::str_to_ident("field"),
88 vec
![cx
.expr_addr_of(field
.span
,
89 field
.self_
.clone())]);
92 // normal struct/struct variant
93 expr
= cx
.expr_method_call(span
,
95 token
::str_to_ident("debug_struct"),
99 let name
= cx
.expr_lit(field
.span
, ast
::Lit_
::LitStr(
100 token
::get_ident(field
.name
.clone().unwrap()),
101 ast
::StrStyle
::CookedStr
));
102 expr
= cx
.expr_method_call(span
,
104 token
::str_to_ident("field"),
106 cx
.expr_addr_of(field
.span
,
107 field
.self_
.clone())]);
114 cx
.expr_method_call(span
,
116 token
::str_to_ident("finish"),