Skip to main content

forge_doc/parser/
item.rs

1use crate::Comments;
2
3pub use super::source::{
4    ContractSource, EnumSource, ErrorSource, EventSource, FunctionSource, ParseSource,
5    StructSource, VariableSource,
6};
7
8/// The parsed item.
9#[derive(Clone, Debug, PartialEq)]
10pub struct ParseItem {
11    /// The parse tree source.
12    pub source: ParseSource,
13    /// Item comments.
14    pub comments: Comments,
15    /// Children items.
16    pub children: Vec<Self>,
17    /// Formatted code string.
18    pub code: String,
19}
20
21/// Defines a method that filters [ParseItem]'s children and returns the source data of the
22/// children matching the target variant as well as its comments.
23/// Returns [Option::None] if no children matching the variant are found.
24macro_rules! filter_children_fn {
25    ($vis:vis fn $name:ident(&self, $variant:ident) -> $ret:ty) => {
26        /// Filter children items for matching variants.
27        $vis fn $name(&self) -> Option<Vec<(&$ret, &Comments, &String)>> {
28            let items = self.children.iter().filter_map(|item| match item.source {
29                ParseSource::$variant(ref inner) => Some((inner, &item.comments, &item.code)),
30                _ => None,
31            });
32            let items = items.collect::<Vec<_>>();
33            if !items.is_empty() {
34                Some(items)
35            } else {
36                None
37            }
38        }
39    };
40}
41
42/// Defines a method that returns the inner element if it matches the variant.
43macro_rules! as_inner_source {
44    ($vis:vis fn $name:ident(&self, $variant:ident) -> $ret:ty) => {
45        /// Return inner element if it matches the variant.
46        /// If the element doesn't match, returns [None].
47        $vis fn $name(&self) -> Option<&$ret> {
48            match self.source {
49                ParseSource::$variant(ref inner) => Some(inner),
50                _ => None
51            }
52        }
53    };
54}
55
56impl ParseItem {
57    /// Create new instance of [ParseItem].
58    pub fn new(source: ParseSource) -> Self {
59        Self {
60            source,
61            comments: Default::default(),
62            children: Default::default(),
63            code: Default::default(),
64        }
65    }
66
67    /// Set comments on the [ParseItem].
68    pub fn with_comments(mut self, comments: Comments) -> Self {
69        self.comments = comments;
70        self
71    }
72
73    /// Set children on the [ParseItem].
74    pub fn with_children(mut self, children: Vec<Self>) -> Self {
75        self.children = children;
76        self
77    }
78
79    /// Set the code string for this [ParseItem].
80    pub fn with_code(mut self, code: String) -> Self {
81        self.code = code;
82        self
83    }
84
85    /// Format the item's filename.
86    pub fn filename(&self) -> String {
87        let prefix = match &self.source {
88            ParseSource::Contract(c) => c.kind.as_str(),
89            ParseSource::Function(_) => "function",
90            ParseSource::Variable(_) => "variable",
91            ParseSource::Event(_) => "event",
92            ParseSource::Error(_) => "error",
93            ParseSource::Struct(_) => "struct",
94            ParseSource::Enum(_) => "enum",
95            ParseSource::Type(_) => "type",
96        };
97        let ident = self.source.ident();
98        format!("{prefix}.{ident}.md")
99    }
100
101    filter_children_fn!(pub fn variables(&self, Variable) -> VariableSource);
102    filter_children_fn!(pub fn functions(&self, Function) -> FunctionSource);
103    filter_children_fn!(pub fn events(&self, Event) -> EventSource);
104    filter_children_fn!(pub fn errors(&self, Error) -> ErrorSource);
105    filter_children_fn!(pub fn structs(&self, Struct) -> StructSource);
106    filter_children_fn!(pub fn enums(&self, Enum) -> EnumSource);
107
108    as_inner_source!(pub fn as_contract(&self, Contract) -> ContractSource);
109    as_inner_source!(pub fn as_variable(&self, Variable) -> VariableSource);
110    as_inner_source!(pub fn as_function(&self, Function) -> FunctionSource);
111}