@@ -1366,18 +1366,16 @@ impl Emitter {
13661366 fn emit_statement_block ( & mut self , arg : & StatementBlock , begin_kw : & str , end_kw : & str ) {
13671367 self . token_will_push ( & arg. l_brace . l_brace_token . replace ( begin_kw) ) ;
13681368
1369- let statement_block_list: Vec < _ > = arg
1370- . statement_block_list
1371- . iter ( )
1372- . map ( |x| Into :: < Vec < _ > > :: into ( x. statement_block_group . as_ref ( ) ) )
1373- . collect ( ) ;
1374-
13751369 let mut base = 0 ;
13761370 let mut n_newlines = 0 ;
1377- for x in & statement_block_list {
1378- for x in x {
1379- ( base, n_newlines) = self . emit_declaration_in_statement_block ( x, base, n_newlines) ;
1380- }
1371+ let mut suppress_newline = false ;
1372+ for x in & arg. statement_block_list {
1373+ ( base, n_newlines) = self . hoist_declarations_in_group (
1374+ & x. statement_block_group ,
1375+ base,
1376+ n_newlines,
1377+ & mut suppress_newline,
1378+ ) ;
13811379 }
13821380
13831381 let mut n_newlines = 0 ;
@@ -1394,6 +1392,72 @@ impl Emitter {
13941392 self . token ( & arg. r_brace . r_brace_token . replace ( end_kw) ) ;
13951393 }
13961394
1395+ /// Phase-1 hoist of let/var/const declarations to the block top, keeping
1396+ /// each group's `ifdef/`elsif/`else/`endif guards: flattening them would
1397+ /// emit both arms of an #[ifdef]/#[else] pair unguarded into one scope.
1398+ fn hoist_declarations_in_group (
1399+ & mut self ,
1400+ group : & StatementBlockGroup ,
1401+ mut base : usize ,
1402+ mut n_newlines : usize ,
1403+ suppress_newline : & mut bool ,
1404+ ) -> ( usize , usize ) {
1405+ let items: Vec < & StatementBlockItem > = group. into ( ) ;
1406+ let has_declaration = items. iter ( ) . any ( |x| {
1407+ !matches ! (
1408+ x,
1409+ StatementBlockItem :: Statement ( _) | StatementBlockItem :: ConcatenationAssignment ( _)
1410+ )
1411+ } ) ;
1412+ if !has_declaration {
1413+ return ( base, n_newlines) ;
1414+ }
1415+
1416+ let ifdef_attributes: Vec < _ > = group
1417+ . statement_block_group_list
1418+ . iter ( )
1419+ . filter ( |x| is_conditional_attribute ( & x. attribute ) )
1420+ . collect ( ) ;
1421+
1422+ for ( j, x) in ifdef_attributes. iter ( ) . enumerate ( ) {
1423+ if j == 0 && !* suppress_newline {
1424+ self . newline_list ( n_newlines) ;
1425+ n_newlines += 1 ;
1426+ base += 1 ;
1427+ }
1428+ self . attribute ( & x. attribute ) ;
1429+ }
1430+ if !ifdef_attributes. is_empty ( ) {
1431+ * suppress_newline = true ;
1432+ }
1433+
1434+ match & * group. statement_block_group_group {
1435+ StatementBlockGroupGroup :: BlockLBraceStatementBlockGroupGroupListRBrace ( x) => {
1436+ for x in & x. statement_block_group_group_list {
1437+ ( base, n_newlines) = self . hoist_declarations_in_group (
1438+ & x. statement_block_group ,
1439+ base,
1440+ n_newlines,
1441+ suppress_newline,
1442+ ) ;
1443+ }
1444+ }
1445+ StatementBlockGroupGroup :: StatementBlockItem ( x) => {
1446+ ( base, n_newlines) = self . emit_declaration_in_statement_block (
1447+ x. statement_block_item . as_ref ( ) ,
1448+ base,
1449+ n_newlines,
1450+ suppress_newline,
1451+ ) ;
1452+ }
1453+ }
1454+
1455+ for _ in ifdef_attributes {
1456+ self . attribute_end ( ) ;
1457+ }
1458+ ( base, n_newlines)
1459+ }
1460+
13971461 /// Emit one `StatementBlockGroup`, opening its conditional attributes once
13981462 /// around the whole group: a multi-statement `#[ifdef] block` gets a single
13991463 /// `ifdef/`endif pair, and nested groups keep their own guards. `suppress_newline`
@@ -1470,6 +1534,7 @@ impl Emitter {
14701534 arg : & StatementBlockItem ,
14711535 base : usize ,
14721536 n_newlines : usize ,
1537+ suppress_newline : & mut bool ,
14731538 ) -> ( usize , usize ) {
14741539 if matches ! (
14751540 arg,
@@ -1478,7 +1543,11 @@ impl Emitter {
14781543 return ( base, n_newlines) ;
14791544 }
14801545
1481- self . newline_list ( n_newlines) ;
1546+ if * suppress_newline {
1547+ * suppress_newline = false ;
1548+ } else {
1549+ self . newline_list ( n_newlines) ;
1550+ }
14821551 self . clear_adjust_line ( ) ;
14831552 match arg {
14841553 StatementBlockItem :: VarDeclaration ( x) => {
0 commit comments