@@ -19,6 +19,7 @@ use rustc_ast_pretty::pprust;
1919use  rustc_span:: { BytePos ,  DUMMY_SP ,  Ident ,  Span ,  Symbol } ; 
2020use  tracing:: debug; 
2121
22+ use  crate :: Config ; 
2223use  crate :: comment:: { 
2324    CharClasses ,  FindUncommented ,  FullCodeCharKind ,  LineClasses ,  contains_comment, 
2425} ; 
@@ -27,6 +28,7 @@ use crate::config::lists::*;
2728use  crate :: expr:: { RhsAssignKind ,  rewrite_array,  rewrite_assign_rhs} ; 
2829use  crate :: lists:: { ListFormatting ,  itemize_list,  write_list} ; 
2930use  crate :: overflow; 
31+ use  crate :: parse:: macros:: cfg_select:: parse_cfg_select; 
3032use  crate :: parse:: macros:: lazy_static:: parse_lazy_static; 
3133use  crate :: parse:: macros:: { ParsedMacroArgs ,  parse_expr,  parse_macro_args} ; 
3234use  crate :: rewrite:: { 
@@ -240,6 +242,20 @@ fn rewrite_macro_inner(
240242        } 
241243    } 
242244
245+     if  macro_name. ends_with ( "cfg_select!" )  { 
246+         match  format_cfg_select ( context,  shape,  ts. clone ( ) ,  mac. span ( ) )  { 
247+             Ok ( rw)  => return  Ok ( rw) , 
248+             Err ( err)  => match  err { 
249+                 // We will move on to parsing macro args just like other macros 
250+                 // if we could not parse cfg_select! with known syntax 
251+                 RewriteError :: MacroFailure  {  kind,  span :  _ } 
252+                     if  kind == MacroErrorKind :: ParseFailure  => { } 
253+                 // If formatting fails even though parsing succeeds, return the err early 
254+                 other => return  Err ( other) , 
255+             } , 
256+         } 
257+     } 
258+ 
243259    let  ParsedMacroArgs  { 
244260        args :  arg_vec, 
245261        vec_with_semi, 
@@ -1288,17 +1304,19 @@ impl MacroBranch {
12881304
12891305        let  old_body = context. snippet ( self . body ) . trim ( ) ; 
12901306        let  has_block_body = old_body. starts_with ( '{' ) ; 
1291-         let  mut  prefix_width = 5 ;  // 5 = " => {" 
1292-         if  context. config . style_edition ( )  >= StyleEdition :: Edition2024  { 
1293-             if  has_block_body { 
1294-                 prefix_width = 6 ;  // 6 = " => {{" 
1295-             } 
1296-         } 
1307+ 
1308+         let  prefix =
1309+             if  context. config . style_edition ( )  >= StyleEdition :: Edition2024  && has_block_body { 
1310+                 " => {{" 
1311+             }  else  { 
1312+                 " => {" 
1313+             } ; 
1314+ 
12971315        let  mut  result = format_macro_args ( 
12981316            context, 
12991317            self . args . clone ( ) , 
13001318            shape
1301-                 . sub_width ( prefix_width ) 
1319+                 . sub_width ( prefix . len ( ) ) 
13021320                . max_width_error ( shape. width ,  self . span ) ?, 
13031321        ) ?; 
13041322
@@ -1321,10 +1339,63 @@ impl MacroBranch {
13211339        let  ( body_str,  substs)  =
13221340            replace_names ( old_body) . macro_error ( MacroErrorKind :: ReplaceMacroVariable ,  self . span ) ?; 
13231341
1324-         let  mut  config = context . config . clone ( ) ; 
1325-         config. set ( ) . show_parse_errors ( false ) ; 
1342+         let  mut  new_body = 
1343+              Self :: try_format_rhs ( & context . config ,  shape ,  has_block_body ,   & body_str ,   self . span ) ? ; 
13261344
1327-         result += " {" ; 
1345+         // Undo our replacement of macro variables. 
1346+         // FIXME: this could be *much* more efficient. 
1347+         for  ( old,  new)  in  & substs { 
1348+             if  old_body. contains ( new)  { 
1349+                 debug ! ( "rewrite_macro_def: bailing matching variable: `{}`" ,  new) ; 
1350+                 return  Err ( RewriteError :: MacroFailure  { 
1351+                     kind :  MacroErrorKind :: ReplaceMacroVariable , 
1352+                     span :  self . span , 
1353+                 } ) ; 
1354+             } 
1355+             new_body = new_body. replace ( new,  old) ; 
1356+         } 
1357+ 
1358+         Self :: emit_formatted_body ( 
1359+             & context. config , 
1360+             & shape, 
1361+             & mut  result, 
1362+             has_block_body, 
1363+             & new_body, 
1364+         ) ; 
1365+ 
1366+         Ok ( result) 
1367+     } 
1368+ 
1369+     fn  emit_formatted_body ( 
1370+         config :  & Config , 
1371+         shape :  & Shape , 
1372+         result :  & mut  String , 
1373+         has_block_body :  bool , 
1374+         body :  & str , 
1375+     )  { 
1376+         * result += " {" ; 
1377+ 
1378+         if  has_block_body { 
1379+             * result += body. trim ( ) ; 
1380+         }  else  if  !body. is_empty ( )  { 
1381+             * result += "\n " ; 
1382+             * result += & body; 
1383+             * result += & shape. indent . to_string ( & config) ; 
1384+         } 
1385+ 
1386+         * result += "}" ; 
1387+     } 
1388+ 
1389+     fn  try_format_rhs ( 
1390+         config :  & Config , 
1391+         shape :  Shape , 
1392+         has_block_body :  bool , 
1393+         body_str :  & str , 
1394+         span :  Span , 
1395+     )  -> RewriteResult  { 
1396+         // This is a best-effort, reporting parse errors is not helpful. 
1397+         let  mut  config = config. clone ( ) ; 
1398+         config. set ( ) . show_parse_errors ( false ) ; 
13281399
13291400        let  body_indent = if  has_block_body { 
13301401            shape. indent 
@@ -1335,33 +1406,34 @@ impl MacroBranch {
13351406        config. set ( ) . max_width ( new_width) ; 
13361407
13371408        // First try to format as items, then as statements. 
1338-         let  new_body_snippet = match  crate :: format_snippet ( & body_str,  & config,  true )  { 
1339-             Some ( new_body)  => new_body, 
1340-             None  => { 
1341-                 let  new_width = new_width + config. tab_spaces ( ) ; 
1342-                 config. set ( ) . max_width ( new_width) ; 
1343-                 match  crate :: format_code_block ( & body_str,  & config,  true )  { 
1344-                     Some ( new_body)  => new_body, 
1345-                     None  => { 
1346-                         return  Err ( RewriteError :: MacroFailure  { 
1347-                             kind :  MacroErrorKind :: Unknown , 
1348-                             span :  self . span , 
1349-                         } ) ; 
1350-                     } 
1351-                 } 
1409+         let  new_body_snippet = ' blk:  { 
1410+             if  let  Some ( new_body)  = crate :: format_snippet ( & body_str,  & config,  true )  { 
1411+                 break  ' blk new_body; 
13521412            } 
1413+ 
1414+             let  new_width = config. max_width ( )  + config. tab_spaces ( ) ; 
1415+             config. set ( ) . max_width ( new_width) ; 
1416+ 
1417+             if  let  Some ( new_body)  = crate :: format_code_block ( & body_str,  & config,  true )  { 
1418+                 break  ' blk new_body; 
1419+             } 
1420+ 
1421+             return  Err ( RewriteError :: MacroFailure  { 
1422+                 kind :  MacroErrorKind :: Unknown , 
1423+                 span, 
1424+             } ) ; 
13531425        } ; 
13541426
13551427        if  !filtered_str_fits ( & new_body_snippet. snippet ,  config. max_width ( ) ,  shape)  { 
13561428            return  Err ( RewriteError :: ExceedsMaxWidth  { 
13571429                configured_width :  shape. width , 
1358-                 span :   self . span , 
1430+                 span, 
13591431            } ) ; 
13601432        } 
13611433
13621434        // Indent the body since it is in a block. 
13631435        let  indent_str = body_indent. to_string ( & config) ; 
1364-         let  mut   new_body = LineClasses :: new ( new_body_snippet. snippet . trim_end ( ) ) 
1436+         let  new_body = LineClasses :: new ( new_body_snippet. snippet . trim_end ( ) ) 
13651437            . enumerate ( ) 
13661438            . fold ( 
13671439                ( String :: new ( ) ,  true ) , 
@@ -1377,30 +1449,7 @@ impl MacroBranch {
13771449            ) 
13781450            . 0 ; 
13791451
1380-         // Undo our replacement of macro variables. 
1381-         // FIXME: this could be *much* more efficient. 
1382-         for  ( old,  new)  in  & substs { 
1383-             if  old_body. contains ( new)  { 
1384-                 debug ! ( "rewrite_macro_def: bailing matching variable: `{}`" ,  new) ; 
1385-                 return  Err ( RewriteError :: MacroFailure  { 
1386-                     kind :  MacroErrorKind :: ReplaceMacroVariable , 
1387-                     span :  self . span , 
1388-                 } ) ; 
1389-             } 
1390-             new_body = new_body. replace ( new,  old) ; 
1391-         } 
1392- 
1393-         if  has_block_body { 
1394-             result += new_body. trim ( ) ; 
1395-         }  else  if  !new_body. is_empty ( )  { 
1396-             result += "\n " ; 
1397-             result += & new_body; 
1398-             result += & shape. indent . to_string ( & config) ; 
1399-         } 
1400- 
1401-         result += "}" ; 
1402- 
1403-         Ok ( result) 
1452+         Ok ( new_body) 
14041453    } 
14051454} 
14061455
@@ -1464,6 +1513,89 @@ fn format_lazy_static(
14641513    Ok ( result) 
14651514} 
14661515
1516+ fn  format_cfg_select ( 
1517+     context :  & RewriteContext < ' _ > , 
1518+     shape :  Shape , 
1519+     ts :  TokenStream , 
1520+     span :  Span , 
1521+ )  -> RewriteResult  { 
1522+     let  mut  result = String :: with_capacity ( 1024 ) ; 
1523+ 
1524+     result. push_str ( "cfg_select! {" ) ; 
1525+ 
1526+     let  branches = parse_cfg_select ( context,  ts) . macro_error ( MacroErrorKind :: ParseFailure ,  span) ?; 
1527+ 
1528+     let  shape = shape
1529+         . block_indent ( context. config . tab_spaces ( ) ) 
1530+         . with_max_width ( context. config ) ; 
1531+ 
1532+     result. push_str ( & shape. indent . to_string_with_newline ( context. config ) ) ; 
1533+ 
1534+     for  ( rule,  rhs,  _)  in  branches. reachable  { 
1535+         result. push_str ( & rule. rewrite_result ( context,  shape) ?) ; 
1536+         result. push_str ( " =>" ) ; 
1537+         result. push_str ( & format_cfg_select_rhs ( context,  shape,  rhs) ?) ; 
1538+     } 
1539+ 
1540+     if  let  Some ( ( _,  rhs,  _) )  = branches. wildcard  { 
1541+         result. push_str ( "_ =>" ) ; 
1542+         result. push_str ( & format_cfg_select_rhs ( context,  shape,  rhs) ?) ; 
1543+     } 
1544+ 
1545+     for  ( lhs,  rhs,  _)  in  branches. unreachable  { 
1546+         use  rustc_parse:: parser:: cfg_select:: CfgSelectPredicate ; 
1547+ 
1548+         match  lhs { 
1549+             CfgSelectPredicate :: Cfg ( rule)  => { 
1550+                 result. push_str ( & rule. rewrite_result ( context,  shape) ?) ; 
1551+             } 
1552+             CfgSelectPredicate :: Wildcard ( _)  => { 
1553+                 result. push ( '_' ) ; 
1554+             } 
1555+         } 
1556+ 
1557+         result. push_str ( " =>" ) ; 
1558+         result. push_str ( & format_cfg_select_rhs ( context,  shape,  rhs) ?) ; 
1559+     } 
1560+ 
1561+     // Emit the final `}` at the correct indentation level. 
1562+     result. truncate ( result. len ( )  - context. config . tab_spaces ( ) ) ; 
1563+     result. push ( '}' ) ; 
1564+ 
1565+     Ok ( result) 
1566+ } 
1567+ 
1568+ fn  format_cfg_select_rhs ( 
1569+     context :  & RewriteContext < ' _ > , 
1570+     shape :  Shape , 
1571+     ts :  TokenStream , 
1572+ )  -> RewriteResult  { 
1573+     let  has_block_body = false ; 
1574+ 
1575+     let  span = ts
1576+         . iter ( ) 
1577+         . map ( |tt| tt. span ( ) ) 
1578+         . reduce ( Span :: to) 
1579+         . unwrap_or_default ( ) ; 
1580+ 
1581+     let  old_body = context. snippet ( span) . trim ( ) ; 
1582+     let  new_body =
1583+         MacroBranch :: try_format_rhs ( & context. config ,  shape,  has_block_body,  old_body,  span) ?; 
1584+ 
1585+     let  mut  result = String :: new ( ) ; 
1586+     MacroBranch :: emit_formatted_body ( 
1587+         & context. config , 
1588+         & shape, 
1589+         & mut  result, 
1590+         has_block_body, 
1591+         & new_body, 
1592+     ) ; 
1593+ 
1594+     result. push_str ( & shape. indent . to_string_with_newline ( context. config ) ) ; 
1595+ 
1596+     Ok ( result) 
1597+ } 
1598+ 
14671599fn  rewrite_macro_with_items ( 
14681600    context :  & RewriteContext < ' _ > , 
14691601    items :  & [ MacroArg ] , 
0 commit comments