1+ use std:: ops:: Deref ;
2+
13use rustpython_ast:: {
24 text_size:: TextRange , Alias , Arg , Arguments , BoolOp , CmpOp , Comprehension , ExceptHandler ,
35 ExceptHandlerExceptHandler , Expr , ExprAttribute , ExprAwait , ExprBinOp , ExprBoolOp , ExprCall ,
@@ -13,7 +15,7 @@ use rustpython_ast::{
1315 StmtWhile , StmtWith , TypeParam , TypeParamParamSpec , TypeParamTypeVar , TypeParamTypeVarTuple ,
1416 UnaryOp , WithItem ,
1517} ;
16- use rustpython_ast:: { Constant , Int } ;
18+ use rustpython_ast:: { Constant , ConversionFlag , Int } ;
1719
1820enum Precedence {
1921 NamedExpr = 1 ,
@@ -42,6 +44,8 @@ impl Precedence {
4244 self as usize
4345 }
4446}
47+
48+ #[ allow( dead_code) ]
4549const EXPR_PRECEDENCE : usize = 9 ;
4650
4751fn get_precedence ( node : & Expr < TextRange > ) -> usize {
@@ -686,7 +690,7 @@ impl Unparser {
686690 Expr :: Compare ( data) => self . unparse_expr_compare ( data) ,
687691 Expr :: Call ( data) => self . unparse_expr_call ( data) ,
688692 Expr :: FormattedValue ( data) => self . unparse_expr_formatted_value ( data) ,
689- Expr :: JoinedStr ( data) => self . unparse_expr_joined_str ( data) ,
693+ Expr :: JoinedStr ( data) => self . unparse_expr_joined_str ( data, false ) ,
690694 Expr :: Constant ( data) => self . unparse_expr_constant ( data) ,
691695 Expr :: Attribute ( data) => self . unparse_expr_attribute ( data) ,
692696 Expr :: Subscript ( data) => self . unparse_expr_subscript ( data) ,
@@ -944,31 +948,57 @@ impl Unparser {
944948 self . write_str ( " " ) ;
945949 }
946950 self . write_str ( inner_expr) ;
947-
951+ if node. conversion != ConversionFlag :: None {
952+ self . write_str ( "!" ) ;
953+ let buf = & [ node. conversion as u8 ] ;
954+ let c = std:: str:: from_utf8 ( buf) . unwrap ( ) ;
955+ self . write_str ( c) ;
956+ }
948957 if let Some ( format_spec) = & node. format_spec {
949958 self . write_str ( ":" ) ;
950- self . unparse_expr ( format_spec) ;
959+ match format_spec. deref ( ) {
960+ Expr :: JoinedStr ( joined_str) => {
961+ if joined_str. values . len ( ) > 0 {
962+ self . unparse_expr_joined_str ( joined_str, true ) ;
963+ }
964+ }
965+ _ => self . unparse_expr ( & format_spec) ,
966+ } ;
951967 }
952968 self . write_str ( "}" ) ;
953969 }
954970
955- fn unparse_expr_joined_str ( & mut self , node : & ExprJoinedStr < TextRange > ) {
956- self . write_str ( "f" ) ;
957- if node. values . len ( ) == 0 {
958- self . write_str ( "\" \" " ) ;
971+ fn unparse_expr_joined_str ( & mut self , node : & ExprJoinedStr < TextRange > , is_spec : bool ) {
972+ if !is_spec {
973+ self . write_str ( "f" ) ;
959974 }
960- for ( index, expr) in node. values . iter ( ) . enumerate ( ) {
975+ let mut expr_source = String :: new ( ) ;
976+ for expr in node. values . iter ( ) {
961977 let mut inner_unparser = Unparser :: new ( ) ;
962- inner_unparser. unparse_expr ( expr) ;
963- let mut expr_source = inner_unparser. source . as_str ( ) ;
964- if index > 0 {
965- expr_source = expr_source. trim_start_matches ( "\" " )
978+ match expr {
979+ Expr :: Constant ( ExprConstant { value, .. } ) => {
980+ if let Constant :: Str ( str_) = value {
981+ inner_unparser. write_str ( str_) ;
982+ } else {
983+ unreachable ! ( )
984+ }
985+ }
986+ _ => {
987+ inner_unparser. unparse_expr ( expr) ;
988+ }
966989 }
967990
968- if index != node. values . len ( ) - 1 {
969- expr_source = expr_source. trim_end_matches ( "\" " )
970- }
991+ expr_source += inner_unparser. source . as_str ( ) ;
992+ }
993+
994+ if is_spec {
971995 self . write_str ( & expr_source) ;
996+ } else {
997+ let escaped_source = rustpython_literal:: escape:: UnicodeEscape :: new_repr ( & expr_source)
998+ . str_repr ( )
999+ . to_string ( )
1000+ . unwrap ( ) ;
1001+ self . write_str ( & escaped_source) ;
9721002 }
9731003 }
9741004
0 commit comments