telety_impl/visitor/
apply_aliases.rs

1use crate::alias;
2
3pub struct ApplyAliases<'map> {
4    map: &'map alias::Map<'map>,
5    apply_free_types: bool,
6    apply_associated_types: bool,
7}
8
9impl<'map> ApplyAliases<'map> {
10    pub(crate) fn new(map: &'map alias::Map) -> Self {
11        Self {
12            map,
13            apply_free_types: true,
14            apply_associated_types: true,
15        }
16    }
17
18    pub fn set_apply_free_types(&mut self, apply_free_types: bool) {
19        self.apply_free_types = apply_free_types;
20    }
21
22    pub fn set_apply_associated_types(&mut self, apply_associated_types: bool) {
23        self.apply_associated_types = apply_associated_types;
24    }
25}
26
27impl<'map> directed_visit::syn::visit::FullMut for ApplyAliases<'map> {
28    fn visit_type_path_mut<D>(
29        visitor: directed_visit::Visitor<'_, D, Self>,
30        node: &mut syn::TypePath,
31    ) where
32        D: directed_visit::DirectMut<Self, syn::TypePath> + ?Sized,
33    {
34        'apply: {
35            // Replace `Self` with a global path
36            // TODO Associated types, if ever supported, would also be done here
37            if node.qself.is_none() && node.path.is_ident("Self") {
38                if visitor.apply_associated_types
39                    && let Some(self_mapped) = visitor.map.get_self()
40                {
41                    node.path = self_mapped.to_path();
42                }
43                break 'apply;
44            }
45
46            if visitor.apply_free_types
47                && node.qself.is_none()
48                && let Ok(Some(mapped)) = visitor.map.get_alias(&node.path)
49            {
50                node.path = mapped.to_path();
51                break 'apply;
52            }
53        };
54
55        directed_visit::Visitor::visit_mut(visitor, node);
56    }
57
58    fn visit_trait_bound_mut<D>(
59        visitor: directed_visit::Visitor<'_, D, Self>,
60        node: &mut syn::TraitBound,
61    ) where
62        D: directed_visit::DirectMut<Self, syn::TraitBound> + ?Sized,
63    {
64        if visitor.apply_free_types
65            && let Ok(Some(mapped)) = visitor.map.get_alias(&node.path)
66        {
67            let mut kept = vec![];
68
69            if let Some(last_segment) = node.path.segments.last_mut()
70                && let syn::PathArguments::AngleBracketed(args) =
71                    std::mem::take(&mut last_segment.arguments)
72            {
73                for arg in args.args {
74                    if let arg @ (syn::GenericArgument::AssocType(_)
75                    | syn::GenericArgument::AssocConst(_)
76                    | syn::GenericArgument::Constraint(_)) = arg
77                    {
78                        kept.push(arg);
79                    }
80                }
81            }
82
83            node.path = mapped.to_path();
84            if let Some(last_segment) = node.path.segments.last_mut()
85                && !kept.is_empty()
86            {
87                if let syn::PathArguments::None = &mut last_segment.arguments {
88                    last_segment.arguments =
89                        syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
90                            colon2_token: Default::default(),
91                            lt_token: Default::default(),
92                            args: Default::default(),
93                            gt_token: Default::default(),
94                        });
95                }
96
97                if let syn::PathArguments::AngleBracketed(args) = &mut last_segment.arguments {
98                    args.args.extend(kept);
99                }
100            }
101        }
102    }
103}