]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_ext/concat_idents.rs
Auto merge of #38867 - alexcrichton:ignore-test-on-windows, r=brson
[rust.git] / src / libsyntax_ext / concat_idents.rs
1 // Copyright 2012 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 syntax::ast;
12 use syntax::ext::base::*;
13 use syntax::ext::base;
14 use syntax::feature_gate;
15 use syntax::parse::token;
16 use syntax::ptr::P;
17 use syntax_pos::Span;
18 use syntax::tokenstream::TokenTree;
19
20 pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
21                               sp: Span,
22                               tts: &[TokenTree])
23                               -> Box<base::MacResult + 'cx> {
24     if !cx.ecfg.enable_concat_idents() {
25         feature_gate::emit_feature_err(&cx.parse_sess,
26                                        "concat_idents",
27                                        sp,
28                                        feature_gate::GateIssue::Language,
29                                        feature_gate::EXPLAIN_CONCAT_IDENTS);
30         return base::DummyResult::expr(sp);
31     }
32
33     let mut res_str = String::new();
34     for (i, e) in tts.iter().enumerate() {
35         if i & 1 == 1 {
36             match *e {
37                 TokenTree::Token(_, token::Comma) => {}
38                 _ => {
39                     cx.span_err(sp, "concat_idents! expecting comma.");
40                     return DummyResult::expr(sp);
41                 }
42             }
43         } else {
44             match *e {
45                 TokenTree::Token(_, token::Ident(ident)) => res_str.push_str(&ident.name.as_str()),
46                 _ => {
47                     cx.span_err(sp, "concat_idents! requires ident args.");
48                     return DummyResult::expr(sp);
49                 }
50             }
51         }
52     }
53     let res = ast::Ident::from_str(&res_str);
54
55     struct Result {
56         ident: ast::Ident,
57         span: Span,
58     };
59
60     impl Result {
61         fn path(&self) -> ast::Path {
62             ast::Path {
63                 span: self.span,
64                 segments: vec![self.ident.into()],
65             }
66         }
67     }
68
69     impl base::MacResult for Result {
70         fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
71             Some(P(ast::Expr {
72                 id: ast::DUMMY_NODE_ID,
73                 node: ast::ExprKind::Path(None, self.path()),
74                 span: self.span,
75                 attrs: ast::ThinVec::new(),
76             }))
77         }
78
79         fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
80             Some(P(ast::Ty {
81                 id: ast::DUMMY_NODE_ID,
82                 node: ast::TyKind::Path(None, self.path()),
83                 span: self.span,
84             }))
85         }
86     }
87
88     Box::new(Result {
89         ident: res,
90         span: sp,
91     })
92 }