1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use std::iter::FromIterator;
use syn::File;
use syn::Ident;
use syn::UseTree;

pub fn extract_modules(file: &File) -> Vec<Ident> {
    let mut idents = vec![];
    for item in file.items.iter() {
        if let syn::Item::Use(u) = item {
            match &u.tree {
                UseTree::Path(path) => {
                    idents.push(path.ident.clone());
                }
                UseTree::Name(name) => {
                    idents.push(name.ident.clone());
                }
                UseTree::Rename(rename) => {
                    idents.push(rename.ident.clone());
                }
                _ => log::warn!("{:?} is not supported yet.", u),
            }
        }
    }
    idents.sort();
    idents.dedup();
    Vec::from_iter(idents.into_iter())
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_extract_modules() {
        let source_code = r"
                use std::env;
                use non_std::fun;
                use my_library::tool;
                use ::std::collections;
                use another_library;
                use glob_lib::*;
                use rename_lib as lib;
                
                fn main() {
                }
        ";
        let file = syn::parse_file(source_code).unwrap();
        let idents = extract_modules(&file);
        let idents = idents
            .iter()
            .map(|ident| ident.to_string())
            .collect::<Vec<_>>();
        assert_eq!(
            vec![
                "another_library",
                "glob_lib",
                "my_library",
                "non_std",
                "rename_lib",
                "std"
            ],
            idents
        );
    }
}