Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 1 | use rustc_data_structures::thin_vec::ThinVec; |
| 2 | |
| 3 | use syntax::ast; |
| 4 | use syntax::ext::base::{self, *}; |
Chih-Hung Hsieh | da60c85 | 2019-12-19 14:56:55 -0800 | [diff] [blame] | 5 | use syntax::parse::token::{self, Token}; |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 6 | use syntax::ptr::P; |
| 7 | use syntax_pos::Span; |
Chih-Hung Hsieh | 43f0694 | 2019-12-19 15:01:08 -0800 | [diff] [blame^] | 8 | use syntax_pos::symbol::Symbol; |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 9 | use syntax::tokenstream::TokenTree; |
| 10 | |
| 11 | pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>, |
| 12 | sp: Span, |
| 13 | tts: &[TokenTree]) |
| 14 | -> Box<dyn base::MacResult + 'cx> { |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 15 | if tts.is_empty() { |
| 16 | cx.span_err(sp, "concat_idents! takes 1 or more arguments."); |
| 17 | return DummyResult::any(sp); |
| 18 | } |
| 19 | |
| 20 | let mut res_str = String::new(); |
| 21 | for (i, e) in tts.iter().enumerate() { |
| 22 | if i & 1 == 1 { |
| 23 | match *e { |
Chih-Hung Hsieh | da60c85 | 2019-12-19 14:56:55 -0800 | [diff] [blame] | 24 | TokenTree::Token(Token { kind: token::Comma, .. }) => {} |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 25 | _ => { |
| 26 | cx.span_err(sp, "concat_idents! expecting comma."); |
| 27 | return DummyResult::any(sp); |
| 28 | } |
| 29 | } |
| 30 | } else { |
| 31 | match *e { |
Chih-Hung Hsieh | da60c85 | 2019-12-19 14:56:55 -0800 | [diff] [blame] | 32 | TokenTree::Token(Token { kind: token::Ident(name, _), .. }) => |
| 33 | res_str.push_str(&name.as_str()), |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 34 | _ => { |
| 35 | cx.span_err(sp, "concat_idents! requires ident args."); |
| 36 | return DummyResult::any(sp); |
| 37 | } |
| 38 | } |
| 39 | } |
| 40 | } |
| 41 | |
Chih-Hung Hsieh | 43f0694 | 2019-12-19 15:01:08 -0800 | [diff] [blame^] | 42 | let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.id)); |
Inna Palant | ff3f07a | 2019-07-11 16:15:26 -0700 | [diff] [blame] | 43 | |
| 44 | struct ConcatIdentsResult { ident: ast::Ident } |
| 45 | |
| 46 | impl base::MacResult for ConcatIdentsResult { |
| 47 | fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> { |
| 48 | Some(P(ast::Expr { |
| 49 | id: ast::DUMMY_NODE_ID, |
| 50 | node: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)), |
| 51 | span: self.ident.span, |
| 52 | attrs: ThinVec::new(), |
| 53 | })) |
| 54 | } |
| 55 | |
| 56 | fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> { |
| 57 | Some(P(ast::Ty { |
| 58 | id: ast::DUMMY_NODE_ID, |
| 59 | node: ast::TyKind::Path(None, ast::Path::from_ident(self.ident)), |
| 60 | span: self.ident.span, |
| 61 | })) |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | Box::new(ConcatIdentsResult { ident }) |
| 66 | } |