@@ -185,6 +185,19 @@ fn write_visit_trait(file: &mut File, config: &Config) -> Result<(), Box<dyn std
185185 writeln ! ( file, "}}" ) ?;
186186 writeln ! ( file) ?;
187187
188+ // Map C field types (e.g. `rbs_type_name`) to the corresponding
189+ // visitor method name (e.g. `type_name` -> `visit_type_name_node`).
190+ let visitor_method_names: std:: collections:: HashMap < String , String > = config
191+ . nodes
192+ . iter ( )
193+ . map ( |node| {
194+ let c_type = convert_name ( & node. name , CIdentifier :: Type ) ;
195+ let c_type = c_type. strip_suffix ( "_t" ) . unwrap_or ( & c_type) . to_string ( ) ;
196+ let method = convert_name ( node. variant_name ( ) , CIdentifier :: Method ) ;
197+ ( c_type, method)
198+ } )
199+ . collect ( ) ;
200+
188201 for node in & config. nodes {
189202 let node_variant_name = node. variant_name ( ) ;
190203 let method_name = convert_name ( node_variant_name, CIdentifier :: Method ) ;
@@ -195,6 +208,94 @@ fn write_visit_trait(file: &mut File, config: &Config) -> Result<(), Box<dyn std
195208 "pub fn visit_{}_node<V: Visit + ?Sized>(visitor: &mut V, node: &{}Node) {{" ,
196209 method_name, node_variant_name
197210 ) ?;
211+
212+ if let Some ( fields) = & node. fields {
213+ for field in fields {
214+ let field_method_name = if field. name == "type" {
215+ "type_"
216+ } else {
217+ field. name . as_str ( )
218+ } ;
219+
220+ match field. c_type . as_str ( ) {
221+ "rbs_node" => {
222+ if field. optional {
223+ writeln ! (
224+ file,
225+ " if let Some(item) = node.{field_method_name}() {{"
226+ ) ?;
227+ writeln ! ( file, " visitor.visit(&item);" ) ?;
228+ writeln ! ( file, " }}" ) ?;
229+ } else {
230+ writeln ! ( file, " visitor.visit(&node.{field_method_name}());" ) ?;
231+ }
232+ }
233+
234+ "rbs_node_list" => {
235+ if field. optional {
236+ writeln ! (
237+ file,
238+ " if let Some(list) = node.{field_method_name}() {{"
239+ ) ?;
240+ writeln ! ( file, " for item in list.iter() {{" ) ?;
241+ writeln ! ( file, " visitor.visit(&item);" ) ?;
242+ writeln ! ( file, " }}" ) ?;
243+ writeln ! ( file, " }}" ) ?;
244+ } else {
245+ writeln ! (
246+ file,
247+ " for item in node.{field_method_name}().iter() {{"
248+ ) ?;
249+ writeln ! ( file, " visitor.visit(&item);" ) ?;
250+ writeln ! ( file, " }}" ) ?;
251+ }
252+ }
253+
254+ "rbs_hash" => {
255+ if field. optional {
256+ writeln ! (
257+ file,
258+ " if let Some(hash) = node.{field_method_name}() {{"
259+ ) ?;
260+ writeln ! ( file, " for (key, value) in hash.iter() {{" ) ?;
261+ writeln ! ( file, " visitor.visit(&key);" ) ?;
262+ writeln ! ( file, " visitor.visit(&value);" ) ?;
263+ writeln ! ( file, " }}" ) ?;
264+ writeln ! ( file, " }}" ) ?;
265+ } else {
266+ writeln ! (
267+ file,
268+ " for (key, value) in node.{field_method_name}().iter() {{"
269+ ) ?;
270+ writeln ! ( file, " visitor.visit(&key);" ) ?;
271+ writeln ! ( file, " visitor.visit(&value);" ) ?;
272+ writeln ! ( file, " }}" ) ?;
273+ }
274+ }
275+
276+ _ => {
277+ if let Some ( visit_method_name) = visitor_method_names. get ( & field. c_type ) {
278+ if field. optional {
279+ writeln ! (
280+ file,
281+ " if let Some(item) = node.{field_method_name}() {{"
282+ ) ?;
283+ writeln ! (
284+ file,
285+ " visitor.visit_{visit_method_name}_node(&item);"
286+ ) ?;
287+ writeln ! ( file, " }}" ) ?;
288+ } else {
289+ writeln ! (
290+ file,
291+ " visitor.visit_{visit_method_name}_node(&node.{field_method_name}());"
292+ ) ?;
293+ }
294+ }
295+ }
296+ }
297+ }
298+ }
198299 writeln ! ( file, "}}" ) ?;
199300 writeln ! ( file) ?;
200301 }
0 commit comments