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