1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 use crate::utils::crate_ident_new;
4 use proc_macro::token_stream::IntoIter as ProcIter;
5 use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
6 use std::iter::Peekable;
7 
8 #[derive(Clone, Copy, Debug)]
9 enum BorrowKind {
10     Weak,
11     WeakAllowNone,
12     Strong,
13 }
14 
15 impl BorrowKind {
to_str(self) -> &'static str16     fn to_str(self) -> &'static str {
17         match self {
18             Self::Weak => "@weak",
19             Self::WeakAllowNone => "@weak-allow-none",
20             Self::Strong => "@strong",
21         }
22     }
23 }
24 
25 enum WrapperKind {
26     DefaultPanic,
27     DefaultReturn(String),
28 }
29 
30 impl WrapperKind {
to_str(&self) -> String31     fn to_str(&self) -> String {
32         match *self {
33             Self::DefaultPanic => "@default-panic".to_owned(),
34             Self::DefaultReturn(ref r) => format!("@default-return {}", r),
35         }
36     }
37 
keyword(&self) -> &'static str38     fn keyword(&self) -> &'static str {
39         match *self {
40             Self::DefaultPanic => "default-panic",
41             Self::DefaultReturn(_) => "default-return",
42         }
43     }
44 }
45 
46 #[derive(Debug)]
47 struct ElemToClone {
48     name: String,
49     alias: Option<String>,
50     borrow_kind: BorrowKind,
51 }
52 
53 impl ElemToClone {
to_str_before(&self) -> String54     fn to_str_before(&self) -> String {
55         match self.borrow_kind {
56             BorrowKind::Weak | BorrowKind::WeakAllowNone => format!(
57                 "let {} = {}::clone::Downgrade::downgrade(&{});",
58                 if let Some(ref a) = self.alias {
59                     a
60                 } else {
61                     &self.name
62                 },
63                 crate_ident_new(),
64                 self.name,
65             ),
66             BorrowKind::Strong => format!(
67                 "let {} = {}.clone();",
68                 if let Some(ref a) = self.alias {
69                     a
70                 } else {
71                     &self.name
72                 },
73                 self.name,
74             ),
75         }
76     }
77 
to_str_after(&self, wrapper_kind: &Option<WrapperKind>) -> String78     fn to_str_after(&self, wrapper_kind: &Option<WrapperKind>) -> String {
79         let name = if let Some(ref a) = self.alias {
80             a
81         } else {
82             &self.name
83         };
84         match (self.borrow_kind, wrapper_kind) {
85             (BorrowKind::Weak, Some(WrapperKind::DefaultPanic)) => {
86                 format!(
87                     "\
88 let {0} = match {1}::clone::Upgrade::upgrade(&{0}) {{
89     Some(val) => val,
90     None => panic!(
91         \"failed to upgrade `{0}` (if you don't want to panic, use @default-return)\",
92     ),
93 }};",
94                     name,
95                     crate_ident_new(),
96                 )
97             }
98             (BorrowKind::Weak, Some(WrapperKind::DefaultReturn(ref r))) => {
99                 format!(
100                     "\
101 let {0} = match {1}::clone::Upgrade::upgrade(&{0}) {{
102     Some(val) => val,
103     None => {{
104         {1}::g_debug!(
105             {1}::CLONE_MACRO_LOG_DOMAIN,
106             \"Failed to upgrade {0}\",
107         );
108         let ___return_value = || {{ {2} }};
109         return ___return_value();
110     }}
111 }};",
112                     name,
113                     crate_ident_new(),
114                     r,
115                 )
116             }
117             (BorrowKind::Weak, None) => {
118                 format!(
119                     "\
120 let {0} = match {1}::clone::Upgrade::upgrade(&{0}) {{
121     Some(val) => val,
122     None => {{
123         {1}::g_debug!(
124             {1}::CLONE_MACRO_LOG_DOMAIN,
125             \"Failed to upgrade {0}\",
126         );
127         return;
128     }}
129 }};",
130                     name,
131                     crate_ident_new(),
132                 )
133             }
134             (BorrowKind::WeakAllowNone, _) => format!(
135                 "let {0} = {1}::clone::Upgrade::upgrade(&{0});",
136                 name,
137                 crate_ident_new(),
138             ),
139             _ => String::new(),
140         }
141     }
142 }
143 
144 enum SimpleToken {
145     Punct(&'static str),
146     Ident(&'static str),
147 }
148 
149 impl SimpleToken {
to_str(&self) -> &str150     fn to_str(&self) -> &str {
151         match *self {
152             Self::Punct(p) => p,
153             Self::Ident(i) => i,
154         }
155     }
156 }
157 
158 impl PartialEq<TokenTree> for SimpleToken {
eq(&self, other: &TokenTree) -> bool159     fn eq(&self, other: &TokenTree) -> bool {
160         match (self, other) {
161             (SimpleToken::Punct(p1), TokenTree::Punct(ref p2)) => *p1 == p2.to_string(),
162             (SimpleToken::Ident(i1), TokenTree::Ident(ref i2)) => *i1 == i2.to_string(),
163             _ => false,
164         }
165     }
166 }
167 
is_punct(elem: &TokenTree, punct: &str) -> bool168 fn is_punct(elem: &TokenTree, punct: &str) -> bool {
169     match elem {
170         TokenTree::Punct(ref p) => p.to_string() == punct,
171         _ => false,
172     }
173 }
174 
175 enum TokenCheck {
176     UnexpectedToken(String, String),
177     UnexpectedEnd(String),
178 }
179 
check_tokens( tokens_to_check: &[SimpleToken], parts: &mut Peekable<ProcIter>, ) -> Result<(), TokenCheck>180 fn check_tokens(
181     tokens_to_check: &[SimpleToken],
182     parts: &mut Peekable<ProcIter>,
183 ) -> Result<(), TokenCheck> {
184     let mut tokens = String::new();
185 
186     for token in tokens_to_check {
187         if let Some(next) = parts.next() {
188             if *token != next {
189                 return Err(TokenCheck::UnexpectedToken(
190                     tokens,
191                     token.to_str().to_owned(),
192                 ));
193             }
194             tokens.push_str(token.to_str());
195         } else {
196             return Err(TokenCheck::UnexpectedEnd(tokens));
197         }
198     }
199     Ok(())
200 }
201 
202 #[doc(alias = "get_full_ident")]
full_ident(parts: &mut Peekable<ProcIter>, borrow_kind: BorrowKind) -> String203 fn full_ident(parts: &mut Peekable<ProcIter>, borrow_kind: BorrowKind) -> String {
204     let mut name = String::new();
205     let mut prev_is_ident = false;
206 
207     loop {
208         match parts.peek() {
209             Some(TokenTree::Punct(p)) => {
210                 let p_s = p.to_string();
211                 if p_s == "," || p_s == "=" {
212                     break;
213                 } else if p_s == "." {
214                     if !prev_is_ident {
215                         panic!("Unexpected `.` after `{}`", borrow_kind.to_str());
216                     }
217                     prev_is_ident = false;
218                     name.push('.');
219                     parts.next();
220                 } else if name.is_empty() {
221                     panic!("Expected ident, found `{}`", p_s);
222                 } else {
223                     panic!("Expected ident, found `{}` after `{}`", p_s, name);
224                 }
225             }
226             Some(TokenTree::Ident(i)) => {
227                 if prev_is_ident {
228                     break;
229                 }
230                 prev_is_ident = true;
231                 name.push_str(&i.to_string());
232                 parts.next();
233             }
234             Some(x) if name.is_empty() => panic!("Expected ident, found `{}`", x.to_string()),
235             Some(x) => panic!("Expected ident, found `{}` after `{}`", x.to_string(), name),
236             None => panic!("Unexpected end after ident `{}`", name),
237         }
238     }
239     if name.is_empty() {
240         panic!(
241             "Expected ident, found `{}`",
242             parts.next().unwrap().to_string()
243         );
244     }
245     name
246 }
247 
248 #[doc(alias = "get_keyword")]
keyword(parts: &mut Peekable<ProcIter>) -> String249 fn keyword(parts: &mut Peekable<ProcIter>) -> String {
250     let mut ret = String::new();
251     let mut prev_is_ident = false;
252     let mut stored = false;
253 
254     loop {
255         match parts.peek() {
256             Some(TokenTree::Ident(i)) => {
257                 if prev_is_ident {
258                     break;
259                 }
260                 prev_is_ident = true;
261                 if stored {
262                     ret.push('-');
263                     stored = false;
264                 }
265                 ret.push_str(&i.to_string());
266             }
267             Some(TokenTree::Punct(p)) if p.to_string() == "-" => {
268                 if !prev_is_ident {
269                     break;
270                 }
271                 // This is to prevent to push `-` if the next item isn't an ident.
272                 prev_is_ident = false;
273                 stored = true;
274             }
275             _ => break,
276         }
277         parts.next();
278     }
279     ret
280 }
281 
parse_ident(parts: &mut Peekable<ProcIter>, elements: &mut Vec<ElemToClone>)282 fn parse_ident(parts: &mut Peekable<ProcIter>, elements: &mut Vec<ElemToClone>) {
283     let borrow_kind = match keyword(parts).as_str() {
284         "strong" => BorrowKind::Strong,
285         "weak" => BorrowKind::Weak,
286         "weak-allow-none" => BorrowKind::WeakAllowNone,
287         "default-return" => panic!("`@default-return` should be after `=>`"),
288         "default-panic" => panic!("`@default-panic` should be after `=>`"),
289         k => panic!(
290             "Unknown keyword `{}`, only `weak`, `weak-allow-none` and `strong` are allowed",
291             k,
292         ),
293     };
294     let name = full_ident(parts, borrow_kind);
295     let alias = match parts.peek() {
296         Some(TokenTree::Ident(p)) if p.to_string() == "as" => {
297             parts.next();
298             match parts.next() {
299                 Some(TokenTree::Ident(i)) => Some(i.to_string()),
300                 Some(x) => panic!(
301                     "Expected ident after `as` keyword, found `{}`",
302                     x.to_string()
303                 ),
304                 None => panic!("Unexpected end after `as` keyword"),
305             }
306         }
307         Some(TokenTree::Ident(p)) => panic!("Unexpected `{}`", p.to_string()),
308         _ => None,
309     };
310     if name == "self" && alias.is_none() {
311         panic!(
312             "Can't use `self` as variable name. Try storing it in a temporary variable or \
313                 rename it using `as`."
314         );
315     } else if name.ends_with('.') {
316         panic!("Invalid variable name: `{}`", name);
317     } else if name.contains('.') && alias.is_none() {
318         panic!(
319             "`{}`: Field accesses are not allowed as is, you must rename it!",
320             name
321         );
322     }
323     elements.push(ElemToClone {
324         name,
325         alias,
326         borrow_kind,
327     });
328 }
329 
delimiter_to_string(delimiter: Delimiter, open: bool) -> &'static str330 fn delimiter_to_string(delimiter: Delimiter, open: bool) -> &'static str {
331     match delimiter {
332         Delimiter::Parenthesis => {
333             if open {
334                 "("
335             } else {
336                 ")"
337             }
338         }
339         Delimiter::Brace => {
340             if open {
341                 "{"
342             } else {
343                 "}"
344             }
345         }
346         Delimiter::Bracket => {
347             if open {
348                 "["
349             } else {
350                 "]"
351             }
352         }
353         Delimiter::None => "",
354     }
355 }
356 
group_to_string(g: &Group) -> String357 fn group_to_string(g: &Group) -> String {
358     format!(
359         "{}{}{}",
360         delimiter_to_string(g.delimiter(), true),
361         tokens_to_string(g.stream().into_iter().peekable()),
362         delimiter_to_string(g.delimiter(), false),
363     )
364 }
365 
366 #[doc(alias = "get_expr")]
expr(parts: &mut Peekable<ProcIter>) -> String367 fn expr(parts: &mut Peekable<ProcIter>) -> String {
368     let mut ret = String::new();
369     let mut total = 0;
370     match parts.next() {
371         Some(TokenTree::Literal(l)) => ret.push_str(&l.to_string()),
372         Some(TokenTree::Ident(i)) => ret.push_str(&i.to_string()),
373         Some(TokenTree::Punct(p)) => match p.to_string().as_str() {
374             "[" | "{" | "(" => {
375                 total += 1;
376             }
377             x => panic!("Unexpected token `{}` after `@default-return`", x),
378         },
379         Some(TokenTree::Group(g)) => return group_to_string(&g),
380         None => panic!("Unexpected end after `@default-return`"),
381     };
382     loop {
383         match parts.peek() {
384             Some(TokenTree::Punct(p)) => {
385                 let p_s = p.to_string();
386                 if p_s == "{" || p_s == "(" || p_s == "[" || p_s == "<" {
387                     total += 1;
388                 } else if p_s == "}" || p_s == ")" || p_s == "]" || p_s == ">" {
389                     total -= 1;
390                 } else if p_s == "," && total == 0 {
391                     return ret;
392                 }
393                 ret.push_str(&p_s);
394             }
395             Some(TokenTree::Group(g)) => {
396                 ret.push_str(&group_to_string(g));
397             }
398             Some(x) => {
399                 if total == 0 && !ret.ends_with(':') {
400                     return ret;
401                 }
402                 ret.push_str(&x.to_string())
403             }
404             None => panic!(
405                 "Unexpected end after `{}`. Did you forget a `,` after the @default-return value?",
406                 ret
407             ),
408         }
409         parts.next();
410     }
411 }
412 
413 #[doc(alias = "get_return_kind")]
return_kind(parts: &mut Peekable<ProcIter>) -> WrapperKind414 fn return_kind(parts: &mut Peekable<ProcIter>) -> WrapperKind {
415     match check_tokens(
416         &[SimpleToken::Ident("default"), SimpleToken::Punct("-")],
417         parts,
418     ) {
419         Err(TokenCheck::UnexpectedToken(tokens, unexpected_token)) => {
420             panic!("Unknown keyword `{}{}`", tokens, unexpected_token);
421         }
422         Err(TokenCheck::UnexpectedEnd(tokens)) => {
423             panic!("Unexpected end after tokens `{}`", tokens);
424         }
425         Ok(()) => {}
426     }
427     match parts.next() {
428         Some(TokenTree::Ident(i)) => {
429             let i_s = i.to_string();
430             if i_s == "panic" {
431                 return WrapperKind::DefaultPanic;
432             } else if i_s != "return" {
433                 panic!("Unknown keyword `@default-{}`", i_s);
434             }
435         }
436         Some(x) => panic!("Unknown token `{}` after `@default-`", x.to_string()),
437         None => panic!("Unexpected end after `@default-`"),
438     }
439     WrapperKind::DefaultReturn(expr(parts))
440 }
441 
parse_return_kind(parts: &mut Peekable<ProcIter>) -> Option<WrapperKind>442 fn parse_return_kind(parts: &mut Peekable<ProcIter>) -> Option<WrapperKind> {
443     match parts.peek() {
444         Some(TokenTree::Punct(p)) if p.to_string() == "@" => {}
445         None => panic!("Unexpected end 2"),
446         _ => return None,
447     }
448     parts.next();
449     let ret = return_kind(parts);
450     match check_tokens(&[SimpleToken::Punct(",")], parts) {
451         Err(TokenCheck::UnexpectedToken(_, unexpected_token)) => {
452             panic!(
453                 "Expected `,` after `{}`, found `{}`",
454                 ret.to_str(),
455                 unexpected_token
456             );
457         }
458         Err(TokenCheck::UnexpectedEnd(tokens)) => {
459             panic!("Expected `,` after `{}{}`", ret.to_str(), tokens);
460         }
461         Ok(()) => {}
462     }
463     Some(ret)
464 }
465 
466 enum BlockKind {
467     Closure(Vec<TokenTree>),
468     ClosureWrappingAsync(Vec<TokenTree>),
469     AsyncClosure(Vec<TokenTree>),
470     AsyncBlock,
471 }
472 
473 impl BlockKind {
474     #[doc(alias = "get_closure")]
closure(self) -> Option<Vec<TokenTree>>475     fn closure(self) -> Option<Vec<TokenTree>> {
476         match self {
477             Self::AsyncBlock => None,
478             Self::Closure(c) | Self::ClosureWrappingAsync(c) | Self::AsyncClosure(c) => Some(c),
479         }
480     }
481 }
482 
check_move_after_async(parts: &mut Peekable<ProcIter>)483 fn check_move_after_async(parts: &mut Peekable<ProcIter>) {
484     match parts.next() {
485         Some(TokenTree::Ident(i)) if i.to_string() == "move" => {}
486         // The next checks are just for better error messages.
487         Some(TokenTree::Ident(i)) => {
488             panic!("Expected `move` after `async`, found `{}`", i.to_string());
489         }
490         Some(TokenTree::Punct(p)) => {
491             panic!("Expected `move` after `async`, found `{}`", p.to_string());
492         }
493         Some(TokenTree::Group(g)) => {
494             panic!(
495                 "Expected `move` after `async`, found `{}`",
496                 delimiter_to_string(g.delimiter(), true),
497             );
498         }
499         _ => panic!("Expected `move` after `async`"),
500     }
501 }
502 
check_async_syntax(parts: &mut Peekable<ProcIter>) -> BlockKind503 fn check_async_syntax(parts: &mut Peekable<ProcIter>) -> BlockKind {
504     check_move_after_async(parts);
505     match parts.peek() {
506         Some(TokenTree::Punct(p)) if p.to_string() == "|" => {
507             parts.next();
508             BlockKind::AsyncClosure(closure(parts))
509         }
510         Some(TokenTree::Punct(p)) => {
511             panic!(
512                 "Expected closure or block after `async move`, found `{}`",
513                 p.to_string()
514             );
515         }
516         Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Brace => BlockKind::AsyncBlock,
517         Some(TokenTree::Group(g)) => {
518             panic!(
519                 "Expected closure or block after `async move`, found `{}`",
520                 delimiter_to_string(g.delimiter(), true),
521             );
522         }
523         _ => panic!("Expected closure or block after `async move`"),
524     }
525 }
526 
527 // Returns `true` if this is an async context.
check_before_closure(parts: &mut Peekable<ProcIter>) -> BlockKind528 fn check_before_closure(parts: &mut Peekable<ProcIter>) -> BlockKind {
529     let is_async = match parts.peek() {
530         Some(TokenTree::Ident(i)) if i.to_string() == "move" => false,
531         Some(TokenTree::Ident(i)) if i.to_string() == "async" => true,
532         Some(TokenTree::Ident(i)) if i.to_string() == "default" => {
533             let ret = return_kind(parts);
534             panic!("Missing `@` before `{}`", ret.keyword());
535         }
536         Some(TokenTree::Punct(p)) if p.to_string() == "|" => {
537             panic!("Closure needs to be \"moved\" so please add `move` before closure")
538         }
539         _ => panic!("Missing `move` and closure declaration"),
540     };
541     parts.next();
542     if is_async {
543         return check_async_syntax(parts);
544     }
545     match parts.next() {
546         Some(TokenTree::Punct(p)) if p.to_string() == "|" => {}
547         Some(x) => panic!("Expected closure, found `{}`", x.to_string()),
548         None => panic!("Expected closure"),
549     }
550     let closure = closure(parts);
551     match parts.peek() {
552         Some(TokenTree::Ident(i)) if i.to_string() == "async" => {
553             parts.next();
554             check_move_after_async(parts);
555             match parts.peek() {
556                 Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Brace => {
557                     BlockKind::ClosureWrappingAsync(closure)
558                 }
559                 // The next matchings are for better error messages.
560                 Some(TokenTree::Punct(p)) => {
561                     panic!(
562                         "Expected block after `| async move`, found `{}`",
563                         p.to_string()
564                     );
565                 }
566                 Some(TokenTree::Group(g)) => {
567                     panic!(
568                         "Expected block after `| async move`, found `{}`",
569                         delimiter_to_string(g.delimiter(), true),
570                     );
571                 }
572                 _ => panic!("Expected block after `| async move`"),
573             }
574         }
575         _ => BlockKind::Closure(closure),
576     }
577 }
578 
579 #[doc(alias = "get_closure")]
closure(parts: &mut Peekable<ProcIter>) -> Vec<TokenTree>580 fn closure(parts: &mut Peekable<ProcIter>) -> Vec<TokenTree> {
581     let mut ret = Vec::new();
582 
583     loop {
584         match parts.next() {
585             Some(TokenTree::Punct(p)) if p.to_string() == "|" => break,
586             Some(x) => ret.push(x),
587             None => panic!("Unexpected end 3"),
588         }
589     }
590     ret
591 }
592 
tokens_to_string(parts: impl Iterator<Item = TokenTree>) -> String593 pub fn tokens_to_string(parts: impl Iterator<Item = TokenTree>) -> String {
594     let mut ret = String::new();
595     // This is used in case of "if ident" or other similar cases.
596     let mut prev_is_ident = false;
597     let handle_ident_like = |i: String, ret: &mut String, prev_is_ident: &mut bool| {
598         if *prev_is_ident {
599             ret.push(' ');
600         }
601         ret.push_str(&i);
602         *prev_is_ident = true;
603     };
604 
605     for token in parts {
606         match token {
607             TokenTree::Punct(p) => {
608                 prev_is_ident = false;
609                 ret.push_str(&p.to_string());
610             }
611             TokenTree::Ident(i) => handle_ident_like(i.to_string(), &mut ret, &mut prev_is_ident),
612             TokenTree::Literal(l) => handle_ident_like(l.to_string(), &mut ret, &mut prev_is_ident),
613             TokenTree::Group(g) => {
614                 prev_is_ident = false;
615                 ret.push_str(&group_to_string(&g));
616             }
617         }
618     }
619     ret
620 }
621 
build_closure( parts: Peekable<ProcIter>, elements: Vec<ElemToClone>, return_kind: Option<WrapperKind>, kind: BlockKind, ) -> TokenStream622 fn build_closure(
623     parts: Peekable<ProcIter>,
624     elements: Vec<ElemToClone>,
625     return_kind: Option<WrapperKind>,
626     kind: BlockKind,
627 ) -> TokenStream {
628     let mut body = TokenStream::new();
629 
630     for el in &elements {
631         let stream: TokenStream = el
632             .to_str_after(&return_kind)
633             .parse()
634             .expect("failed to convert element after");
635         body.extend(stream.into_iter().collect::<Vec<_>>());
636     }
637     body.extend(parts.collect::<Vec<_>>());
638 
639     // To prevent to lose the spans in case some errors occur in the code, we need to keep `body`!
640     //
641     // If we replaced everything that follows with a `format!`, it'd look like this:
642     //
643     // format!(
644     //     "{{\n{}\nmove |{}| {{\n{}\nlet ____ret = {{ {} }};\n____ret\n}}\n}}",
645     //     elements
646     //         .iter()
647     //         .map(|x| x.to_str_before())
648     //         .collect::<Vec<_>>()
649     //         .join("\n"),
650     //     closure,
651     //     elements
652     //         .iter()
653     //         .map(|x| x.to_str_after(&return_kind))
654     //         .collect::<Vec<_>>()
655     //         .join("\n"),
656     //     body,
657     // )
658     let mut ret: Vec<TokenTree> = vec![];
659     for el in elements {
660         let stream: TokenStream = el
661             .to_str_before()
662             .parse()
663             .expect("failed to convert element");
664         ret.extend(stream.into_iter().collect::<Vec<_>>());
665     }
666 
667     // This part is creating the TokenStream using the variables that needs to be cloned (from the
668     // @weak and @strong annotations).
669     let mut inner: Vec<TokenTree> = Vec::new();
670     if matches!(kind, BlockKind::ClosureWrappingAsync(_)) {
671         inner.extend(vec![
672             TokenTree::Ident(Ident::new("async", Span::call_site())),
673             TokenTree::Ident(Ident::new("move", Span::call_site())),
674         ]);
675     }
676 
677     let is_async_closure_kind = matches!(kind, BlockKind::AsyncClosure(_));
678     if let Some(closure) = kind.closure() {
679         if is_async_closure_kind {
680             ret.push(TokenTree::Ident(Ident::new("async", Span::call_site())));
681         }
682         ret.extend(vec![
683             TokenTree::Ident(Ident::new("move", Span::call_site())),
684             TokenTree::Punct(Punct::new('|', Spacing::Alone)),
685         ]);
686         ret.extend(closure);
687         ret.extend(vec![TokenTree::Punct(Punct::new('|', Spacing::Alone))]);
688     } else {
689         ret.extend(vec![
690             TokenTree::Ident(Ident::new("async", Span::call_site())),
691             TokenTree::Ident(Ident::new("move", Span::call_site())),
692         ]);
693     }
694     // The commented lines that follow *might* be useful, don't know. Just in case, I'm keeping
695     // them around. You're welcome future me!
696     inner.extend(vec![
697         // TokenTree::Ident(Ident::new("let", Span::call_site())),
698         // TokenTree::Ident(Ident::new("____ret", Span::call_site())),
699         // TokenTree::Punct(Punct::new('=', Spacing::Alone)),
700         TokenTree::Group(Group::new(Delimiter::Brace, body)),
701         // TokenTree::Punct(Punct::new(';', Spacing::Alone)),
702         // TokenTree::Ident(Ident::new("____ret", Span::call_site())),
703     ]);
704     let mut inners = TokenStream::new();
705     inners.extend(inner);
706     ret.extend(vec![TokenTree::Group(Group::new(Delimiter::Brace, inners))]);
707 
708     let mut rets = TokenStream::new();
709     rets.extend(ret);
710 
711     TokenTree::Group(Group::new(Delimiter::Brace, rets)).into()
712 }
713 
clone_inner(item: TokenStream) -> TokenStream714 pub(crate) fn clone_inner(item: TokenStream) -> TokenStream {
715     let mut parts = item.into_iter().peekable();
716     let mut elements = Vec::new();
717     let mut prev_is_ident = false;
718 
719     loop {
720         match parts.next() {
721             Some(TokenTree::Punct(ref p)) => {
722                 let p_s = p.to_string();
723                 if p_s == "=" && parts.peek().map_or_else(|| false, |n| is_punct(n, ">")) {
724                     parts.next();
725                     break;
726                 } else if p_s == "@" {
727                     parse_ident(&mut parts, &mut elements);
728                     prev_is_ident = true;
729                 } else if p_s == "," {
730                     if !prev_is_ident {
731                         panic!("Unexpected `,`");
732                     }
733                     prev_is_ident = false;
734                 } else if p_s == "|" {
735                     if elements.is_empty() {
736                         panic!("If you have nothing to clone, no need to use this macro!");
737                     } else {
738                         panic!("Expected `=>` before closure");
739                     }
740                 }
741             }
742             Some(TokenTree::Ident(i)) => {
743                 panic!(
744                     "Unexpected ident `{}`: you need to specify if this is a weak or a strong \
745                      clone.",
746                     i.to_string(),
747                 );
748             }
749             Some(t) => panic!("Unexpected token `{}`", t.to_string()),
750             None => panic!("Unexpected end 4"),
751         }
752     }
753     if elements.is_empty() {
754         panic!("If you have nothing to clone, no need to use this macro!");
755     }
756     let return_kind = parse_return_kind(&mut parts);
757     let kind = check_before_closure(&mut parts);
758     build_closure(parts, elements, return_kind, kind)
759 }
760