]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_ext/concat_idents.rs
Rollup merge of #61499 - varkor:issue-53457, r=oli-obk
[rust.git] / src / libsyntax_ext / concat_idents.rs
1 use rustc_data_structures::thin_vec::ThinVec;
2
3 use syntax::ast;
4 use syntax::ext::base::{self, *};
5 use syntax::feature_gate;
6 use syntax::parse::token;
7 use syntax::ptr::P;
8 use syntax_pos::Span;
9 use syntax_pos::symbol::{Symbol, sym};
10 use syntax::tokenstream::TokenTree;
11
12 pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>,
13                               sp: Span,
14                               tts: &[TokenTree])
15                               -> Box<dyn base::MacResult + 'cx> {
16     if !cx.ecfg.enable_concat_idents() {
17         feature_gate::emit_feature_err(&cx.parse_sess,
18                                        sym::concat_idents,
19                                        sp,
20                                        feature_gate::GateIssue::Language,
21                                        feature_gate::EXPLAIN_CONCAT_IDENTS);
22     }
23
24     if tts.is_empty() {
25         cx.span_err(sp, "concat_idents! takes 1 or more arguments.");
26         return DummyResult::any(sp);
27     }
28
29     let mut res_str = String::new();
30     for (i, e) in tts.iter().enumerate() {
31         if i & 1 == 1 {
32             match *e {
33                 TokenTree::Token(_, token::Comma) => {}
34                 _ => {
35                     cx.span_err(sp, "concat_idents! expecting comma.");
36                     return DummyResult::any(sp);
37                 }
38             }
39         } else {
40             match *e {
41                 TokenTree::Token(_, token::Ident(ident, _)) =>
42                     res_str.push_str(&ident.as_str()),
43                 _ => {
44                     cx.span_err(sp, "concat_idents! requires ident args.");
45                     return DummyResult::any(sp);
46                 }
47             }
48         }
49     }
50
51     let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.mark));
52
53     struct ConcatIdentsResult { ident: ast::Ident }
54
55     impl base::MacResult for ConcatIdentsResult {
56         fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
57             Some(P(ast::Expr {
58                 id: ast::DUMMY_NODE_ID,
59                 node: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)),
60                 span: self.ident.span,
61                 attrs: ThinVec::new(),
62             }))
63         }
64
65         fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
66             Some(P(ast::Ty {
67                 id: ast::DUMMY_NODE_ID,
68                 node: ast::TyKind::Path(None, ast::Path::from_ident(self.ident)),
69                 span: self.ident.span,
70             }))
71         }
72     }
73
74     Box::new(ConcatIdentsResult { ident })
75 }