turbo_tasks_macros_shared/
self_filter.rs

1use proc_macro2::TokenTree;
2use quote::ToTokens;
3use syn::visit::{Visit, visit_block, visit_expr, visit_item, visit_macro};
4
5pub fn is_self_used(block: &syn::Block) -> bool {
6    let mut finder = SelfFinder { found: false };
7    finder.visit_block(block);
8    finder.found
9}
10
11struct SelfFinder {
12    found: bool,
13}
14
15impl Visit<'_> for SelfFinder {
16    fn visit_block(&mut self, n: &syn::Block) {
17        if self.found {
18            return;
19        }
20
21        visit_block(self, n);
22    }
23
24    fn visit_expr(&mut self, expr: &syn::Expr) {
25        if self.found {
26            return;
27        }
28
29        if let syn::Expr::Path(path) = expr {
30            if path.path.is_ident("self") {
31                self.found = true;
32                return;
33            }
34        }
35
36        visit_expr(self, expr);
37    }
38
39    fn visit_item(&mut self, n: &syn::Item) {
40        if self.found {
41            return;
42        }
43
44        visit_item(self, n);
45    }
46
47    fn visit_item_impl(&mut self, _: &syn::ItemImpl) {
48        // skip children of `impl`: the definition of "self" inside of an impl is different than the
49        // parent scope's definition of "self"
50    }
51
52    fn visit_macro(&mut self, mac: &syn::Macro) {
53        if self.found {
54            return;
55        }
56
57        for token in mac.tokens.to_token_stream() {
58            if contains_self_token(&token) {
59                self.found = true;
60                return;
61            }
62        }
63
64        visit_macro(self, mac);
65    }
66}
67
68fn contains_self_token(tok: &TokenTree) -> bool {
69    match tok {
70        TokenTree::Group(group) => {
71            for token in group.stream() {
72                if contains_self_token(&token) {
73                    return true;
74                }
75            }
76            false
77        }
78        TokenTree::Ident(ident) => ident == "self",
79        TokenTree::Punct(..) | TokenTree::Literal(..) => false,
80    }
81}