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
65
66
67
68
69
use thiserror::Error;

use std::path::Path;
use std::collections::HashSet;

pub fn parse_file_from_path(path: &Path) -> Result<syn::File, DaoError> {
    let file_string = std::fs::read_to_string(path)?;
    let token_stream = syn::parse_file(&file_string)?;
    Ok(token_stream)
}

pub fn filter_attributes(attrs: &[&syn::Attribute]) -> HashSet<String> {
    let mut filtered = HashSet::new();

    for attr in attrs {
        if attr.path.is_ident("cfg") {
            if let Ok(meta) = attr.parse_meta() {
                recurse_filter_meta(meta, &mut filtered);
            }
        }
    }

    filtered
}

fn recurse_filter_meta(meta: syn::Meta, filtered_set: &mut HashSet<String>) {
    match meta {
        syn::Meta::List(list) => {
            for child in list.nested {
                if let syn::NestedMeta::Meta(child_meta) = child {
                    recurse_filter_meta(child_meta, filtered_set);
                }
            }
        },
        syn::Meta::NameValue(name_value) => {
            if name_value.path.is_ident("dao") {
                if let syn::Lit::Str(str) = name_value.lit {
                    filtered_set.insert(str.value());
                }
            }
        },
        _ => {},
    }
}

#[derive(Default)]
pub struct AttributeCollector<'a> {
    pub attributes: Vec<&'a syn::Attribute>,
}

impl<'a> AttributeCollector<'a> {
    pub fn collect_attributes(&mut self, file: &'a syn::File) {
        syn::visit::visit_file(self, file);
    }    
}

impl<'a> syn::visit::Visit<'a> for AttributeCollector<'a> {
    fn visit_attribute(&mut self, attr: &'a syn::Attribute) {
        self.attributes.push(attr);
    }
}

#[derive(Error, Debug)]
pub enum DaoError {
    #[error("IO error: {0}")]
    IOError(#[from] std::io::Error),
    #[error("Error parsing rust code: {0}")]
    SyntaxError(#[from] syn::Error),
}