]>
Commit | Line | Data |
---|---|---|
8bb4bdeb XL |
1 | // Copyright 2012-2017 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 | use attr::HasAttrs; | |
cc61c64b XL |
12 | use ast; |
13 | use codemap::{ExpnInfo, NameAndSpan, ExpnFormat}; | |
8bb4bdeb XL |
14 | use ext::base::ExtCtxt; |
15 | use ext::build::AstBuilder; | |
cc61c64b | 16 | use parse::parser::PathStyle; |
8bb4bdeb XL |
17 | use symbol::Symbol; |
18 | use syntax_pos::Span; | |
19 | ||
cc61c64b XL |
20 | use std::collections::HashSet; |
21 | ||
22 | pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> { | |
8bb4bdeb XL |
23 | let mut result = Vec::new(); |
24 | attrs.retain(|attr| { | |
cc61c64b | 25 | if attr.path != "derive" { |
8bb4bdeb XL |
26 | return true; |
27 | } | |
28 | ||
cc61c64b XL |
29 | match attr.parse_list(cx.parse_sess, |
30 | |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) { | |
31 | Ok(ref traits) if traits.is_empty() => { | |
32 | cx.span_warn(attr.span, "empty trait list in `derive`"); | |
33 | false | |
34 | } | |
35 | Ok(traits) => { | |
36 | result.extend(traits); | |
37 | true | |
38 | } | |
39 | Err(mut e) => { | |
40 | e.emit(); | |
41 | false | |
8bb4bdeb | 42 | } |
8bb4bdeb | 43 | } |
8bb4bdeb XL |
44 | }); |
45 | result | |
46 | } | |
47 | ||
cc61c64b XL |
48 | pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path], item: T) -> T |
49 | where T: HasAttrs, | |
50 | { | |
51 | let (mut names, mut pretty_name) = (HashSet::new(), "derive(".to_owned()); | |
52 | for (i, path) in traits.iter().enumerate() { | |
53 | if i > 0 { | |
54 | pretty_name.push_str(", "); | |
55 | } | |
56 | pretty_name.push_str(&path.to_string()); | |
57 | names.insert(unwrap_or!(path.segments.get(0), continue).identifier.name); | |
8bb4bdeb | 58 | } |
cc61c64b | 59 | pretty_name.push(')'); |
8bb4bdeb | 60 | |
cc61c64b XL |
61 | cx.current_expansion.mark.set_expn_info(ExpnInfo { |
62 | call_site: span, | |
63 | callee: NameAndSpan { | |
64 | format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), | |
65 | span: None, | |
66 | allow_internal_unstable: true, | |
3b2f2976 | 67 | allow_internal_unsafe: false, |
cc61c64b XL |
68 | }, |
69 | }); | |
8bb4bdeb | 70 | |
ea8adc8c | 71 | let span = span.with_ctxt(cx.backtrace()); |
8bb4bdeb | 72 | item.map_attrs(|mut attrs| { |
cc61c64b | 73 | if names.contains(&Symbol::intern("Eq")) && names.contains(&Symbol::intern("PartialEq")) { |
8bb4bdeb XL |
74 | let meta = cx.meta_word(span, Symbol::intern("structural_match")); |
75 | attrs.push(cx.attribute(span, meta)); | |
76 | } | |
cc61c64b | 77 | if names.contains(&Symbol::intern("Copy")) && names.contains(&Symbol::intern("Clone")) { |
8bb4bdeb XL |
78 | let meta = cx.meta_word(span, Symbol::intern("rustc_copy_clone_marker")); |
79 | attrs.push(cx.attribute(span, meta)); | |
80 | } | |
81 | attrs | |
82 | }) | |
83 | } |