]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_ext/concat_idents.rs
Auto merge of #50409 - KiChjang:issue-50343, r=nikomatsakis
[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_pos::symbol::Symbol;
19 use syntax::tokenstream::TokenTree;
20
21 pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
22                               sp: Span,
23                               tts: &[TokenTree])
24                               -> Box<base::MacResult + 'cx> {
25     if !cx.ecfg.enable_concat_idents() {
26         feature_gate::emit_feature_err(&cx.parse_sess,
27                                        "concat_idents",
28                                        sp,
29                                        feature_gate::GateIssue::Language,
30                                        feature_gate::EXPLAIN_CONCAT_IDENTS);
31         return base::DummyResult::expr(sp);
32     }
33
34     if tts.is_empty() {
35         cx.span_err(sp, "concat_idents! takes 1 or more arguments.");
36         return DummyResult::expr(sp);
37     }
38
39     let mut res_str = String::new();
40     for (i, e) in tts.iter().enumerate() {
41         if i & 1 == 1 {
42             match *e {
43                 TokenTree::Token(_, token::Comma) => {}
44                 _ => {
45                     cx.span_err(sp, "concat_idents! expecting comma.");
46                     return DummyResult::expr(sp);
47                 }
48             }
49         } else {
50             match *e {
51                 TokenTree::Token(_, token::Ident(ident, _)) =>
52                     res_str.push_str(&ident.name.as_str()),
53                 _ => {
54                     cx.span_err(sp, "concat_idents! requires ident args.");
55                     return DummyResult::expr(sp);
56                 }
57             }
58         }
59     }
60
61     let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.mark));
62
63     struct ConcatIdentsResult { ident: ast::Ident }
64
65     impl base::MacResult for ConcatIdentsResult {
66         fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
67             Some(P(ast::Expr {
68                 id: ast::DUMMY_NODE_ID,
69                 node: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)),
70                 span: self.ident.span,
71                 attrs: ast::ThinVec::new(),
72             }))
73         }
74
75         fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
76             Some(P(ast::Ty {
77                 id: ast::DUMMY_NODE_ID,
78                 node: ast::TyKind::Path(None, ast::Path::from_ident(self.ident)),
79                 span: self.ident.span,
80             }))
81         }
82     }
83
84     Box::new(ConcatIdentsResult { ident })
85 }