@@ -16,6 +16,13 @@ use crate::{
1616
1717use super :: * ;
1818
19+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
20+ pub ( super ) enum LineFormat {
21+ Oneline ,
22+ Newline ,
23+ Indentation ,
24+ }
25+
1926pub ( super ) fn print_body_hir (
2027 db : & dyn DefDatabase ,
2128 body : & Body ,
@@ -52,7 +59,14 @@ pub(super) fn print_body_hir(
5259 }
5360 } ;
5461
55- let mut p = Printer { db, body, buf : header, indent_level : 0 , needs_indent : false , edition } ;
62+ let mut p = Printer {
63+ db,
64+ body,
65+ buf : header,
66+ indent_level : 0 ,
67+ line_format : LineFormat :: Newline ,
68+ edition,
69+ } ;
5670 if let DefWithBodyId :: FunctionId ( it) = owner {
5771 p. buf . push ( '(' ) ;
5872 let function_data = & db. function_data ( it) ;
@@ -95,12 +109,38 @@ pub(super) fn print_expr_hir(
95109 expr : ExprId ,
96110 edition : Edition ,
97111) -> String {
98- let mut p =
99- Printer { db, body, buf : String :: new ( ) , indent_level : 0 , needs_indent : false , edition } ;
112+ let mut p = Printer {
113+ db,
114+ body,
115+ buf : String :: new ( ) ,
116+ indent_level : 0 ,
117+ line_format : LineFormat :: Newline ,
118+ edition,
119+ } ;
100120 p. print_expr ( expr) ;
101121 p. buf
102122}
103123
124+ pub ( super ) fn print_pat_hir (
125+ db : & dyn DefDatabase ,
126+ body : & Body ,
127+ _owner : DefWithBodyId ,
128+ pat : PatId ,
129+ oneline : bool ,
130+ edition : Edition ,
131+ ) -> String {
132+ let mut p = Printer {
133+ db,
134+ body,
135+ buf : String :: new ( ) ,
136+ indent_level : 0 ,
137+ line_format : if oneline { LineFormat :: Oneline } else { LineFormat :: Newline } ,
138+ edition,
139+ } ;
140+ p. print_pat ( pat) ;
141+ p. buf
142+ }
143+
104144macro_rules! w {
105145 ( $dst: expr, $( $arg: tt) * ) => {
106146 { let _ = write!( $dst, $( $arg) * ) ; }
@@ -109,10 +149,10 @@ macro_rules! w {
109149
110150macro_rules! wln {
111151 ( $dst: expr) => {
112- { let _ = writeln! ( $dst) ; }
152+ { $dst. newline ( ) ; }
113153 } ;
114154 ( $dst: expr, $( $arg: tt) * ) => {
115- { let _ = writeln !( $dst, $( $arg) * ) ; }
155+ { let _ = w !( $dst, $( $arg) * ) ; $dst . newline ( ) ; }
116156 } ;
117157}
118158
@@ -121,24 +161,30 @@ struct Printer<'a> {
121161 body : & ' a Body ,
122162 buf : String ,
123163 indent_level : usize ,
124- needs_indent : bool ,
164+ line_format : LineFormat ,
125165 edition : Edition ,
126166}
127167
128168impl Write for Printer < ' _ > {
129169 fn write_str ( & mut self , s : & str ) -> fmt:: Result {
130170 for line in s. split_inclusive ( '\n' ) {
131- if self . needs_indent {
171+ if matches ! ( self . line_format , LineFormat :: Indentation ) {
132172 match self . buf . chars ( ) . rev ( ) . find ( |ch| * ch != ' ' ) {
133173 Some ( '\n' ) | None => { }
134174 _ => self . buf . push ( '\n' ) ,
135175 }
136176 self . buf . push_str ( & " " . repeat ( self . indent_level ) ) ;
137- self . needs_indent = false ;
138177 }
139178
140179 self . buf . push_str ( line) ;
141- self . needs_indent = line. ends_with ( '\n' ) ;
180+
181+ if matches ! ( self . line_format, LineFormat :: Newline | LineFormat :: Indentation ) {
182+ self . line_format = if line. ends_with ( '\n' ) {
183+ LineFormat :: Indentation
184+ } else {
185+ LineFormat :: Newline
186+ } ;
187+ }
142188 }
143189
144190 Ok ( ( ) )
@@ -161,14 +207,28 @@ impl Printer<'_> {
161207 }
162208 }
163209
210+ // Add a newline if the current line is not empty.
211+ // If the current line is empty, add a space instead.
212+ //
213+ // Do not use [`writeln!()`] or [`wln!()`] here, which will result in
214+ // infinite recursive calls to this function.
164215 fn newline ( & mut self ) {
165- match self . buf . chars ( ) . rev ( ) . find_position ( |ch| * ch != ' ' ) {
166- Some ( ( _, '\n' ) ) | None => { }
167- Some ( ( idx, _) ) => {
168- if idx != 0 {
169- self . buf . drain ( self . buf . len ( ) - idx..) ;
216+ if matches ! ( self . line_format, LineFormat :: Oneline ) {
217+ match self . buf . chars ( ) . last ( ) {
218+ Some ( ' ' ) | None => { }
219+ Some ( _) => {
220+ w ! ( self , " " ) ;
221+ }
222+ }
223+ } else {
224+ match self . buf . chars ( ) . rev ( ) . find_position ( |ch| * ch != ' ' ) {
225+ Some ( ( _, '\n' ) ) | None => { }
226+ Some ( ( idx, _) ) => {
227+ if idx != 0 {
228+ self . buf . drain ( self . buf . len ( ) - idx..) ;
229+ }
230+ w ! ( self , "\n " ) ;
170231 }
171- writeln ! ( self ) . unwrap ( )
172232 }
173233 }
174234 }
@@ -539,12 +599,14 @@ impl Printer<'_> {
539599 w ! ( self , ")" ) ;
540600 }
541601 Pat :: Or ( pats) => {
602+ w ! ( self , "(" ) ;
542603 for ( i, pat) in pats. iter ( ) . enumerate ( ) {
543604 if i != 0 {
544605 w ! ( self , " | " ) ;
545606 }
546607 self . print_pat ( * pat) ;
547608 }
609+ w ! ( self , ")" ) ;
548610 }
549611 Pat :: Record { path, args, ellipsis } => {
550612 match path {
@@ -554,12 +616,37 @@ impl Printer<'_> {
554616
555617 w ! ( self , " {{" ) ;
556618 let edition = self . edition ;
619+ let oneline = matches ! ( self . line_format, LineFormat :: Oneline ) ;
557620 self . indented ( |p| {
558- for arg in args. iter ( ) {
559- w ! ( p, "{}: " , arg. name. display( self . db. upcast( ) , edition) ) ;
560- p. print_pat ( arg. pat ) ;
561- wln ! ( p, "," ) ;
621+ for ( idx, arg) in args. iter ( ) . enumerate ( ) {
622+ let field_name = arg. name . display ( self . db . upcast ( ) , edition) . to_string ( ) ;
623+
624+ let mut same_name = false ;
625+ if let Pat :: Bind { id, subpat : None } = & self . body [ arg. pat ] {
626+ if let Binding { name, mode : BindingAnnotation :: Unannotated , .. } =
627+ & self . body . bindings [ * id]
628+ {
629+ if name. as_str ( ) == field_name {
630+ same_name = true ;
631+ }
632+ }
633+ }
634+
635+ w ! ( p, "{}" , field_name) ;
636+
637+ if !same_name {
638+ w ! ( p, ": " ) ;
639+ p. print_pat ( arg. pat ) ;
640+ }
641+
642+ // Do not print the extra comma if the line format is oneline
643+ if oneline && idx == args. len ( ) - 1 {
644+ w ! ( p, " " ) ;
645+ } else {
646+ wln ! ( p, "," ) ;
647+ }
562648 }
649+
563650 if * ellipsis {
564651 wln ! ( p, ".." ) ;
565652 }
0 commit comments