1use std::collections::HashMap;
2
3use syn::{
4 parse_quote,
5 visit_mut::{visit_file_mut, VisitMut},
6 File, Ident, ItemUse, Path, PathSegment, TypePath, UseTree,
7};
8
9pub fn qualify_types(mut file: File) -> File {
10 let use_items = collect_use_items(&file);
11
12 let mut map = HashMap::new();
13
14 for item in use_items {
15 for_each_use_item(&[], &item.tree, &mut |local_name, path| {
19 map.insert(local_name.to_string(), path);
20 });
21 }
22
23 map.entry("Option".into())
24 .or_insert_with(|| parse_quote!(::std::option::Option));
25
26 map.entry("Box".into())
27 .or_insert_with(|| parse_quote!(::std::boxed::Box));
28
29 map.entry("Vec".into())
30 .or_insert_with(|| parse_quote!(::std::vec::Vec));
31
32 visit_file_mut(&mut Folder { map }, &mut file);
33
34 file
35}
36
37fn for_each_use_item(path: &[Ident], tree: &UseTree, op: &mut impl FnMut(Ident, Path)) {
38 match tree {
39 UseTree::Path(p) => {
40 if p.ident == "self" || p.ident == "super" || p.ident == "crate" {
41 return;
42 }
43
44 let mut path = path.to_vec();
45 path.push(p.ident.clone());
46
47 for_each_use_item(&path, &p.tree, op);
48 }
49 UseTree::Name(name) => {
50 let mut path = path.to_vec();
51 path.push(name.ident.clone());
52 op(
53 name.ident.clone(),
54 Path {
55 leading_colon: None,
56 segments: path.into_iter().map(PathSegment::from).collect(),
57 },
58 );
59 }
60 UseTree::Rename(..) => {}
61 UseTree::Glob(_) => {}
62 UseTree::Group(g) => {
63 for item in &g.items {
64 for_each_use_item(path, item, op);
65 }
66 }
67 }
68}
69
70fn collect_use_items(file: &File) -> Vec<ItemUse> {
71 let mut use_items = Vec::new();
72 for item in &file.items {
73 if let syn::Item::Use(item_use) = item {
74 use_items.push(item_use.clone());
75 }
76 }
77 use_items
78}
79
80struct Folder {
81 map: HashMap<String, Path>,
83}
84
85impl VisitMut for Folder {
86 fn visit_type_path_mut(&mut self, i: &mut TypePath) {
87 if let Some(id) = i.path.get_ident() {
88 if let Some(path) = self.map.get(&id.to_string()) {
89 i.path = path.clone();
90 }
91 }
92
93 syn::visit_mut::visit_type_path_mut(self, i);
94 }
95}