@@ -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,91 @@ 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 ! ( file, " for item in node.{field_method_name}().iter() {{" ) ?;
246+ writeln ! ( file, " visitor.visit(&item);" ) ?;
247+ writeln ! ( file, " }}" ) ?;
248+ }
249+ }
250+
251+ "rbs_hash" => {
252+ if field. optional {
253+ writeln ! (
254+ file,
255+ " if let Some(hash) = node.{field_method_name}() {{"
256+ ) ?;
257+ writeln ! ( file, " for (key, value) in hash.iter() {{" ) ?;
258+ writeln ! ( file, " visitor.visit(&key);" ) ?;
259+ writeln ! ( file, " visitor.visit(&value);" ) ?;
260+ writeln ! ( file, " }}" ) ?;
261+ writeln ! ( file, " }}" ) ?;
262+ } else {
263+ writeln ! (
264+ file,
265+ " for (key, value) in node.{field_method_name}().iter() {{"
266+ ) ?;
267+ writeln ! ( file, " visitor.visit(&key);" ) ?;
268+ writeln ! ( file, " visitor.visit(&value);" ) ?;
269+ writeln ! ( file, " }}" ) ?;
270+ }
271+ }
272+
273+ _ => {
274+ if let Some ( visit_method_name) = visitor_method_names. get ( & field. c_type ) {
275+ if field. optional {
276+ writeln ! (
277+ file,
278+ " if let Some(item) = node.{field_method_name}() {{"
279+ ) ?;
280+ writeln ! (
281+ file,
282+ " visitor.visit_{visit_method_name}_node(&item);"
283+ ) ?;
284+ writeln ! ( file, " }}" ) ?;
285+ } else {
286+ writeln ! (
287+ file,
288+ " visitor.visit_{visit_method_name}_node(&node.{field_method_name}());"
289+ ) ?;
290+ }
291+ }
292+ }
293+ }
294+ }
295+ }
198296 writeln ! ( file, "}}" ) ?;
199297 writeln ! ( file) ?;
200298 }
0 commit comments