@@ -10,7 +10,8 @@ use crate::rewrite::RewriteContext;
1010use  crate :: shape:: { Indent ,  Shape } ; 
1111use  crate :: string:: { rewrite_string,  StringFormat } ; 
1212use  crate :: utils:: { 
13-     count_newlines,  first_line_width,  last_line_width,  trim_left_preserve_layout,  unicode_str_width, 
13+     count_newlines,  first_line_width,  last_line_width,  tab_to_spaces,  trim_left_preserve_layout, 
14+     unicode_str_width, 
1415} ; 
1516use  crate :: { ErrorKind ,  FormattingError } ; 
1617
@@ -1162,14 +1163,6 @@ impl FullCodeCharKind {
11621163        self  == FullCodeCharKind :: InStringCommented 
11631164            || self  == FullCodeCharKind :: StartStringCommented 
11641165    } 
1165- 
1166-     fn  to_codecharkind ( self )  -> CodeCharKind  { 
1167-         if  self . is_comment ( )  { 
1168-             CodeCharKind :: Comment 
1169-         }  else  { 
1170-             CodeCharKind :: Normal 
1171-         } 
1172-     } 
11731166} 
11741167
11751168impl < T >  CharClasses < T > 
@@ -1484,16 +1477,31 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> {
14841477/// functional text. Line style comments contain their ending newlines. 
14851478pub ( crate )  struct  CommentCodeSlices < ' a >  { 
14861479    slice :  & ' a  str , 
1487-     last_slice_kind :  CodeCharKind , 
1488-     last_slice_end :  usize , 
1480+     ungrouped_code_slices :  MultiPeek < UngroupedCommentCodeSlices < ' a > > , 
1481+     offset :  Option < usize > , 
1482+     tab_spaces :  usize , 
14891483} 
14901484
14911485impl < ' a >  CommentCodeSlices < ' a >  { 
14921486    pub ( crate )  fn  new ( slice :  & ' a  str )  -> CommentCodeSlices < ' a >  { 
14931487        CommentCodeSlices  { 
14941488            slice, 
1495-             last_slice_kind :  CodeCharKind :: Comment , 
1496-             last_slice_end :  0 , 
1489+             tab_spaces :  4 , 
1490+             ungrouped_code_slices :  multipeek ( UngroupedCommentCodeSlices :: new ( slice) ) , 
1491+             offset :  None , 
1492+         } 
1493+     } 
1494+ 
1495+     pub ( crate )  fn  with_offset ( 
1496+         slice :  & ' a  str , 
1497+         offset :  usize , 
1498+         tab_spaces :  usize , 
1499+     )  -> CommentCodeSlices < ' a >  { 
1500+         CommentCodeSlices  { 
1501+             slice, 
1502+             tab_spaces, 
1503+             ungrouped_code_slices :  multipeek ( UngroupedCommentCodeSlices :: new ( slice) ) , 
1504+             offset :  Some ( offset) . filter ( |o| * o != 0 ) , 
14971505        } 
14981506    } 
14991507} 
@@ -1502,59 +1510,50 @@ impl<'a> Iterator for CommentCodeSlices<'a> {
15021510    type  Item  = ( CodeCharKind ,  usize ,  & ' a  str ) ; 
15031511
15041512    fn  next ( & mut  self )  -> Option < Self :: Item >  { 
1505-         if  self . last_slice_end  == self . slice . len ( )  { 
1506-             return  None ; 
1507-         } 
1508- 
1509-         let  mut  sub_slice_end = self . last_slice_end ; 
1510-         let  mut  first_whitespace = None ; 
1511-         let  subslice = & self . slice [ self . last_slice_end ..] ; 
1512-         let  mut  iter = CharClasses :: new ( subslice. char_indices ( ) ) ; 
1513- 
1514-         for  ( kind,  ( i,  c) )  in  & mut  iter { 
1515-             let  is_comment_connector = self . last_slice_kind  == CodeCharKind :: Normal 
1516-                 && & subslice[ ..2 ]  == "//" 
1517-                 && [ ' ' ,  '\t' ] . contains ( & c) ; 
1518- 
1519-             if  is_comment_connector && first_whitespace. is_none ( )  { 
1520-                 first_whitespace = Some ( i) ; 
1513+         let  first_chunk = self . ungrouped_code_slices . next ( ) ?; 
1514+         if  first_chunk. 0  == CodeCharKind :: Normal  { 
1515+             if  !first_chunk. 2 . trim ( ) . is_empty ( )  { 
1516+                 self . offset  = Some ( last_line_width ( first_chunk. 2 ) ) . filter ( |o| * o != 0 ) ; 
15211517            } 
1518+             return  Some ( first_chunk) ; 
1519+         } 
15221520
1523-             if  kind. to_codecharkind ( )  == self . last_slice_kind  && !is_comment_connector { 
1524-                 let  last_index = match  first_whitespace { 
1525-                     Some ( j)  => j, 
1526-                     None  => i, 
1527-                 } ; 
1528-                 sub_slice_end = self . last_slice_end  + last_index; 
1529-                 break ; 
1530-             } 
1521+         let  mut  comment_end_index = first_chunk. 1  + first_chunk. 2 . len ( ) ; 
1522+         while  let  Some ( & ( k,  i,  s) )  = self . ungrouped_code_slices . peek ( )  { 
1523+             match  k { 
1524+                 CodeCharKind :: Comment  if  self . offset . is_none ( )  => { 
1525+                     comment_end_index = i + s. len ( ) ; 
1526+                     self . ungrouped_code_slices . next ( ) ?; 
1527+                 } 
1528+                 CodeCharKind :: Comment  => break , 
1529+                 CodeCharKind :: Normal  if  s. trim ( ) . is_empty ( )  && count_newlines ( s)  == 0  => { 
1530+                     let  indent_width = tab_to_spaces ( s,  self . tab_spaces ) ; 
1531+                     if  self . offset . map_or ( false ,  |comment_offset| { 
1532+                         !( indent_width < comment_offset + 2  && comment_offset < indent_width + 2 ) 
1533+                     } )  { 
1534+                         break ; 
1535+                     } 
15311536
1532-             if  !is_comment_connector { 
1533-                 first_whitespace = None ; 
1537+                     match  self . ungrouped_code_slices . peek ( )  { 
1538+                         Some ( ( CodeCharKind :: Comment ,  index,  s) )  => { 
1539+                             comment_end_index = index + s. len ( ) ; 
1540+                             // Advance twice. 
1541+                             self . ungrouped_code_slices . next ( ) ?; 
1542+                             self . ungrouped_code_slices . next ( ) ?; 
1543+                         } 
1544+                         _ => break , 
1545+                     } 
1546+                 } 
1547+                 CodeCharKind :: Normal  => break , 
15341548            } 
15351549        } 
15361550
1537-         if  let  ( None ,  true )  = ( iter. next ( ) ,  sub_slice_end == self . last_slice_end )  { 
1538-             // This was the last subslice. 
1539-             sub_slice_end = match  first_whitespace { 
1540-                 Some ( i)  => self . last_slice_end  + i, 
1541-                 None  => self . slice . len ( ) , 
1542-             } ; 
1543-         } 
1544- 
1545-         let  kind = match  self . last_slice_kind  { 
1546-             CodeCharKind :: Comment  => CodeCharKind :: Normal , 
1547-             CodeCharKind :: Normal  => CodeCharKind :: Comment , 
1548-         } ; 
1549-         let  res = ( 
1550-             kind, 
1551-             self . last_slice_end , 
1552-             & self . slice [ self . last_slice_end ..sub_slice_end] , 
1553-         ) ; 
1554-         self . last_slice_end  = sub_slice_end; 
1555-         self . last_slice_kind  = kind; 
1556- 
1557-         Some ( res) 
1551+         let  comment_start_index = first_chunk. 1 ; 
1552+         Some ( ( 
1553+             CodeCharKind :: Comment , 
1554+             comment_start_index, 
1555+             & self . slice [ comment_start_index..comment_end_index] , 
1556+         ) ) 
15581557    } 
15591558} 
15601559
@@ -1728,7 +1727,6 @@ mod test {
17281727        let  input = "// comment\n     test();" ; 
17291728        let  mut  iter = CommentCodeSlices :: new ( input) ; 
17301729
1731-         assert_eq ! ( ( CodeCharKind :: Normal ,  0 ,  "" ) ,  iter. next( ) . unwrap( ) ) ; 
17321730        assert_eq ! ( 
17331731            ( CodeCharKind :: Comment ,  0 ,  "// comment\n " ) , 
17341732            iter. next( ) . unwrap( ) 
@@ -1742,18 +1740,67 @@ mod test {
17421740
17431741    #[ test]  
17441742    fn  comment_code_slices_three ( )  { 
1745-         let  input = "1 // comment\n      // comment2\n \n " ; 
1743+         let  input = "1 // comment\n   // comment2\n \n " ; 
17461744        let  mut  iter = CommentCodeSlices :: new ( input) ; 
17471745
17481746        assert_eq ! ( ( CodeCharKind :: Normal ,  0 ,  "1 " ) ,  iter. next( ) . unwrap( ) ) ; 
17491747        assert_eq ! ( 
1750-             ( CodeCharKind :: Comment ,  2 ,  "// comment\n     // comment2\n " ) , 
1748+             ( CodeCharKind :: Comment ,  2 ,  "// comment\n   // comment2\n " ) , 
1749+             iter. next( ) . unwrap( ) 
1750+         ) ; 
1751+         assert_eq ! ( ( CodeCharKind :: Normal ,  27 ,  "\n " ) ,  iter. next( ) . unwrap( ) ) ; 
1752+         assert_eq ! ( None ,  iter. next( ) ) ; 
1753+     } 
1754+ 
1755+     #[ test]  
1756+     fn  comment_code_slices_four ( )  { 
1757+         let  input = r#" 
1758+ if x == 3 { 
1759+     x = 4; 
1760+ } // if x == 3 
1761+ // end of block 
1762+ "# ; 
1763+         let  mut  iter = CommentCodeSlices :: new ( input) ; 
1764+ 
1765+         assert_eq ! ( 
1766+             ( 
1767+                 CodeCharKind :: Normal , 
1768+                 0 , 
1769+                 r#" 
1770+ if x == 3 { 
1771+     x = 4; 
1772+ } "# 
1773+             ) , 
1774+             iter. next( ) . unwrap( ) 
1775+         ) ; 
1776+         assert_eq ! ( 
1777+             ( CodeCharKind :: Comment ,  26 ,  "// if x == 3\n " , ) , 
1778+             iter. next( ) . unwrap( ) 
1779+         ) ; 
1780+         assert_eq ! ( 
1781+             ( CodeCharKind :: Comment ,  39 ,  "// end of block\n " ) , 
17511782            iter. next( ) . unwrap( ) 
17521783        ) ; 
1753-         assert_eq ! ( ( CodeCharKind :: Normal ,  29 ,  "\n " ) ,  iter. next( ) . unwrap( ) ) ; 
17541784        assert_eq ! ( None ,  iter. next( ) ) ; 
17551785    } 
17561786
1787+     #[ test]  
1788+     fn  comment_code_slices_five ( )  { 
1789+         let  input = "1 // comment\r \n \r \n   // comment2\r \n " ; 
1790+         let  mut  iter = CommentCodeSlices :: new ( input) ; 
1791+ 
1792+         assert_eq ! ( ( CodeCharKind :: Normal ,  0 ,  "1 " ) ,  iter. next( ) . unwrap( ) ) ; 
1793+         assert_eq ! ( 
1794+             ( CodeCharKind :: Comment ,  2 ,  "// comment\r \n " ) , 
1795+             iter. next( ) . unwrap( ) 
1796+         ) ; 
1797+         assert_eq ! ( ( CodeCharKind :: Normal ,  14 ,  "\r \n   " , ) ,  iter. next( ) . unwrap( ) ) ; 
1798+         assert_eq ! ( 
1799+             ( CodeCharKind :: Comment ,  18 ,  "// comment2\r \n " ) , 
1800+             iter. next( ) . unwrap( ) 
1801+         ) ; 
1802+         assert_eq ! ( None ,  iter. next( ) ) ; 
1803+     } 
17571804    #[ test]  
17581805    #[ rustfmt:: skip]  
17591806    fn  format_doc_comments ( )  { 
0 commit comments