1use thiserror::Error;
2
3use std::path::Path;
4use std::collections::HashSet;
5
6pub fn parse_file_from_path(path: &Path) -> Result<syn::File, DaoError> {
7 let file_string = std::fs::read_to_string(path)?;
8 let token_stream = syn::parse_file(&file_string)?;
9 Ok(token_stream)
10}
11
12pub fn filter_attributes(attrs: &[&syn::Attribute]) -> HashSet<String> {
13 let mut filtered = HashSet::new();
14
15 for attr in attrs {
16 if attr.path.is_ident("cfg") {
17 if let Ok(meta) = attr.parse_meta() {
18 recurse_filter_meta(meta, &mut filtered);
19 }
20 }
21 }
22
23 filtered
24}
25
26fn recurse_filter_meta(meta: syn::Meta, filtered_set: &mut HashSet<String>) {
27 match meta {
28 syn::Meta::List(list) => {
29 for child in list.nested {
30 if let syn::NestedMeta::Meta(child_meta) = child {
31 recurse_filter_meta(child_meta, filtered_set);
32 }
33 }
34 },
35 syn::Meta::NameValue(name_value) => {
36 if name_value.path.is_ident("dao") {
37 if let syn::Lit::Str(str) = name_value.lit {
38 filtered_set.insert(str.value());
39 }
40 }
41 },
42 _ => {},
43 }
44}
45
46#[derive(Default)]
47pub struct AttributeCollector<'a> {
48 pub attributes: Vec<&'a syn::Attribute>,
49}
50
51impl<'a> AttributeCollector<'a> {
52 pub fn collect_attributes(&mut self, file: &'a syn::File) {
53 syn::visit::visit_file(self, file);
54 }
55}
56
57impl<'a> syn::visit::Visit<'a> for AttributeCollector<'a> {
58 fn visit_attribute(&mut self, attr: &'a syn::Attribute) {
59 self.attributes.push(attr);
60 }
61}
62
63#[derive(Error, Debug)]
64pub enum DaoError {
65 #[error("IO error: {0}")]
66 IOError(#[from] std::io::Error),
67 #[error("Error parsing rust code: {0}")]
68 SyntaxError(#[from] syn::Error),
69}