1use crate::parser::{Argument, AstNode, Modifiers, Span};
7
8pub trait AstVisitor {
10 fn visit_program(&mut self, body: &[AstNode], _span: Span) {
12 for node in body {
13 self.visit(node);
14 }
15 }
16
17 fn visit_text(&mut self, content: &str, span: Span) {
19 let _ = (content, span);
20 }
21
22 fn visit_function_call(
24 &mut self,
25 name: &str,
26 args: Option<&Vec<Argument>>,
27 modifiers: &Modifiers,
28 span: Span,
29 ) {
30 let _ = (name, modifiers, span);
31 if let Some(args) = args {
32 for arg in args {
33 self.visit_argument(arg);
34 }
35 }
36 }
37
38 fn visit_argument(&mut self, arg: &Argument) {
40 for part in &arg.parts {
41 self.visit(part);
42 }
43 }
44
45 fn visit_javascript(&mut self, code: &str, span: Span) {
47 let _ = (code, span);
48 }
49
50 fn visit_escaped(&mut self, content: &str, span: Span) {
52 let _ = (content, span);
53 }
54
55 fn visit(&mut self, node: &AstNode) {
57 match node {
58 AstNode::Program { body, span } => self.visit_program(body, *span),
59 AstNode::Text { content, span } => self.visit_text(content, *span),
60 AstNode::FunctionCall {
61 name,
62 args,
63 modifiers,
64 span,
65 ..
66 } => self.visit_function_call(name, args.as_ref(), modifiers, *span),
67 AstNode::JavaScript { code, span } => self.visit_javascript(code, *span),
68 AstNode::Escaped { content, span } => self.visit_escaped(content, *span),
69 }
70 }
71}
72
73pub struct FunctionCollector {
75 pub functions: Vec<String>,
76}
77
78impl FunctionCollector {
79 pub fn new() -> Self {
80 Self {
81 functions: Vec::new(),
82 }
83 }
84}
85
86impl AstVisitor for FunctionCollector {
87 fn visit_function_call(
88 &mut self,
89 name: &str,
90 args: Option<&Vec<Argument>>,
91 modifiers: &Modifiers,
92 span: Span,
93 ) {
94 self.functions.push(name.to_string());
95
96 let _ = (modifiers, span);
98 if let Some(args) = args {
99 for arg in args {
100 self.visit_argument(arg);
101 }
102 }
103 }
104}
105
106#[derive(Default)]
108pub struct NodeCounter {
109 pub text_nodes: usize,
110 pub function_nodes: usize,
111 pub javascript_nodes: usize,
112 pub escaped_nodes: usize,
113}
114
115impl AstVisitor for NodeCounter {
116 fn visit_text(&mut self, _content: &str, _span: Span) {
117 self.text_nodes += 1;
118 }
119
120 fn visit_function_call(
121 &mut self,
122 _name: &str,
123 args: Option<&Vec<Argument>>,
124 _modifiers: &Modifiers,
125 _span: Span,
126 ) {
127 self.function_nodes += 1;
128 if let Some(args) = args {
129 for arg in args {
130 self.visit_argument(arg);
131 }
132 }
133 }
134
135 fn visit_javascript(&mut self, _code: &str, _span: Span) {
136 self.javascript_nodes += 1;
137 }
138
139 fn visit_escaped(&mut self, _content: &str, _span: Span) {
140 self.escaped_nodes += 1;
141 }
142}
143
144pub trait AstVisitorMut {
146 fn visit_mut(&mut self, node: &mut AstNode) {
148 match node {
149 AstNode::Program { body, span } => self.visit_program_mut(body, *span),
150 AstNode::Text { content, span } => self.visit_text_mut(content, *span),
151 AstNode::FunctionCall {
152 name,
153 args,
154 modifiers,
155 span,
156 ..
157 } => self.visit_function_call_mut(name, args, modifiers, *span),
158 AstNode::JavaScript { code, span } => self.visit_javascript_mut(code, *span),
159 AstNode::Escaped { content, span } => self.visit_escaped_mut(content, *span),
160 }
161 }
162
163 fn visit_program_mut(&mut self, body: &mut [AstNode], span: Span) {
164 let _ = span;
165 for node in body {
166 self.visit_mut(node);
167 }
168 }
169
170 fn visit_text_mut(&mut self, content: &mut String, span: Span) {
171 let _ = (content, span);
172 }
173
174 fn visit_function_call_mut(
175 &mut self,
176 name: &mut String,
177 args: &mut Option<Vec<Argument>>,
178 modifiers: &mut Modifiers,
179 span: Span,
180 ) {
181 let _ = (name, modifiers, span);
182 if let Some(args) = args {
183 for arg in args {
184 for part in &mut arg.parts {
185 self.visit_mut(part);
186 }
187 }
188 }
189 }
190
191 fn visit_javascript_mut(&mut self, code: &mut String, span: Span) {
192 let _ = (code, span);
193 }
194
195 fn visit_escaped_mut(&mut self, content: &mut String, span: Span) {
196 let _ = (content, span);
197 }
198}