@@ -319,7 +319,7 @@ impl Node {
319319 let ctx = Ident :: new ( "ctx" , Span :: call_site ( ) ) ;
320320 let kind_str = self . kind . to_string ( ) ;
321321
322- if let Some ( content) = & self . content {
322+ let node_init = if let Some ( content) = & self . content {
323323 let node = match content {
324324 Content :: Static ( lit) => quote ! { #ctx. literal( #kind_str, #lit) } ,
325325 Content :: Computed ( block) => {
@@ -362,97 +362,96 @@ impl Node {
362362 }
363363 }
364364 } ;
365- return self . with_location ( node, & ctx) ;
366- }
365+ quote ! { let __node: yeast:: Id = #node; }
366+ } else {
367+ TokenStream :: new ( )
368+ } ;
367369
368370 let mut stmts = Vec :: new ( ) ;
369371 let mut field_args = Vec :: new ( ) ;
370372
371373 for ( field_counter, field) in self . fields . iter ( ) . enumerate ( ) {
372- let Field :: Named {
373- name,
374- value,
375- optional,
376- } = field
377- else {
378- continue ;
379- } ;
380- let field_name = name. to_string ( ) ;
381- let field_str = field_name
382- . strip_prefix ( "r#" )
383- . unwrap_or ( & field_name)
384- . to_string ( ) ;
385- let temp = Ident :: new (
386- & format ! ( "__field_{field_str}_{field_counter}" ) ,
387- Span :: call_site ( ) ,
388- ) ;
389-
390- match value {
391- Template :: Splice ( block) => {
392- debug_assert ! ( !optional) ;
374+ match field {
375+ Field :: Location { block } => {
393376 let block = rust_block ( block) ;
394377 stmts. push ( quote ! {
395- let mut #temp: Vec <yeast:: Id > = Vec :: new( ) ;
396- yeast:: IntoFieldIds :: extend_into( #block, & mut #temp) ;
397- } ) ;
398- field_args. push ( quote ! {
399- if !#temp. is_empty( ) {
400- __fields. push( ( #field_str, #temp) ) ;
401- }
378+ yeast:: IntoFieldIds :: extend_into( #block, & mut __location_ids) ;
402379 } ) ;
403380 }
404- Template :: Node ( child) if * optional => {
405- let label = fresh_fallible_label ( ) ;
406- let value = child. lower ( & LoweringContext {
407- fallible_scope : Some ( & label) ,
408- } ) ;
409- stmts. push ( quote ! {
410- #[ allow( unused_labels) ]
411- let #temp: :: std:: option:: Option <yeast:: Id > = #label: {
412- :: std:: option:: Option :: Some ( #value)
413- } ;
414- } ) ;
415- field_args. push ( quote ! {
416- if let :: std:: option:: Option :: Some ( __id) = #temp {
417- __fields. push( ( #field_str, vec![ __id] ) ) ;
381+ Field :: Named {
382+ name,
383+ value,
384+ optional,
385+ } => {
386+ let field_name = name. to_string ( ) ;
387+ let field_str = field_name
388+ . strip_prefix ( "r#" )
389+ . unwrap_or ( & field_name)
390+ . to_string ( ) ;
391+ let temp = Ident :: new (
392+ & format ! ( "__field_{field_str}_{field_counter}" ) ,
393+ Span :: call_site ( ) ,
394+ ) ;
395+
396+ match value {
397+ Template :: Splice ( block) => {
398+ debug_assert ! ( !optional) ;
399+ let block = rust_block ( block) ;
400+ stmts. push ( quote ! {
401+ let mut #temp: Vec <yeast:: Id > = Vec :: new( ) ;
402+ yeast:: IntoFieldIds :: extend_into( #block, & mut #temp) ;
403+ } ) ;
404+ field_args. push ( quote ! {
405+ if !#temp. is_empty( ) {
406+ __fields. push( ( #field_str, #temp) ) ;
407+ }
408+ } ) ;
418409 }
419- } ) ;
420- }
421- Template :: Node ( child) => {
422- let value = child. lower ( context) ;
423- stmts. push ( quote ! { let #temp: yeast:: Id = #value; } ) ;
424- field_args. push ( quote ! {
425- __fields. push( ( #field_str, vec![ #temp] ) ) ;
426- } ) ;
410+ Template :: Node ( child) if * optional => {
411+ let label = fresh_fallible_label ( ) ;
412+ let value = child. lower ( & LoweringContext {
413+ fallible_scope : Some ( & label) ,
414+ } ) ;
415+ stmts. push ( quote ! {
416+ #[ allow( unused_labels) ]
417+ let #temp: :: std:: option:: Option <yeast:: Id > = #label: {
418+ :: std:: option:: Option :: Some ( #value)
419+ } ;
420+ } ) ;
421+ field_args. push ( quote ! {
422+ if let :: std:: option:: Option :: Some ( __id) = #temp {
423+ __fields. push( ( #field_str, vec![ __id] ) ) ;
424+ }
425+ } ) ;
426+ }
427+ Template :: Node ( child) => {
428+ let value = child. lower ( context) ;
429+ stmts. push ( quote ! { let #temp: yeast:: Id = #value; } ) ;
430+ field_args. push ( quote ! {
431+ __fields. push( ( #field_str, vec![ #temp] ) ) ;
432+ } ) ;
433+ }
434+ }
427435 }
428436 }
429437 }
430438
431- let node = quote ! {
432- {
433- #( #stmts) *
439+ let build_node = if self . content . is_none ( ) {
440+ quote ! {
434441 let mut __fields: Vec <( & str , Vec <yeast:: Id >) > = Vec :: new( ) ;
435442 #( #field_args) *
436- #ctx. node( #kind_str, __fields)
443+ let __node : yeast :: Id = #ctx. node( #kind_str, __fields) ;
437444 }
445+ } else {
446+ TokenStream :: new ( )
438447 } ;
439- self . with_location ( node, & ctx)
440- }
441-
442- fn with_location ( & self , node : TokenStream , ctx : & Ident ) -> TokenStream {
443- let locations = self . fields . iter ( ) . filter_map ( |field| match field {
444- Field :: Named { .. } => None ,
445- Field :: Location { block } => Some ( rust_block ( block) ) ,
446- } ) ;
447- let locations: Vec < _ > = locations. collect ( ) ;
448- if locations. is_empty ( ) {
449- return node;
450- }
451448
452449 quote ! {
453450 {
454451 let mut __location_ids: Vec <yeast:: Id > = Vec :: new( ) ;
455- #( yeast:: IntoFieldIds :: extend_into( #locations, & mut __location_ids) ; ) *
452+ #node_init
453+ #( #stmts) *
454+ #build_node
456455 let __source_range = __location_ids
457456 . into_iter( )
458457 . filter_map( |__source| {
@@ -461,7 +460,6 @@ impl Node {
461460 . and_then( |__node| __node. source_range( ) )
462461 } )
463462 . reduce( yeast:: Range :: union ) ;
464- let __node: yeast:: Id = #node;
465463 #ctx. set_node_source_range( __node, __source_range)
466464 }
467465 }
0 commit comments