@@ -2,6 +2,7 @@ use crate::{buffer::Buffer, IndentOptions};
22use dioxus_rsx:: * ;
33use proc_macro2:: { LineColumn , Span } ;
44use quote:: ToTokens ;
5+ use regex:: Regex ;
56use std:: {
67 borrow:: Cow ,
78 collections:: { HashMap , VecDeque } ,
@@ -797,8 +798,95 @@ impl<'a> Writer<'a> {
797798 return Err ( std:: fmt:: Error ) ;
798799 } ;
799800
801+ thread_local ! {
802+ static COMMENT_REGEX : Regex = Regex :: new( "\" [^\" ]*\" |(//.*)" ) . unwrap( ) ;
803+ }
804+
800805 let pretty_expr = self . retrieve_formatted_expr ( & expr) . to_string ( ) ;
801- self . write_mulitiline_tokens ( pretty_expr) ?;
806+
807+ // Adding comments back to the formatted expression
808+ let source_text = src_span. source_text ( ) . unwrap_or_default ( ) ;
809+ let mut source_lines = source_text. lines ( ) . peekable ( ) ;
810+ let mut output = String :: from ( "" ) ;
811+ let mut printed_empty_line = false ;
812+
813+ if source_lines. peek ( ) . is_none ( ) {
814+ output = pretty_expr;
815+ } else {
816+ for line in pretty_expr. lines ( ) {
817+ let compacted_pretty_line = line. replace ( " " , "" ) . replace ( "," , "" ) ;
818+ let trimmed_pretty_line = line. trim ( ) ;
819+
820+ // Nested expressions might have comments already. We handle writing all of those
821+ // at the outer level, so we skip them here
822+ if trimmed_pretty_line. starts_with ( "//" ) {
823+ continue ;
824+ }
825+
826+ if !output. is_empty ( ) {
827+ output. push ( '\n' ) ;
828+ }
829+
830+ // pull down any source lines with whitespace until we hit a line that matches our current line.
831+ while let Some ( src) = source_lines. peek ( ) {
832+ let trimmed_src = src. trim ( ) ;
833+
834+ // Write comments and empty lines as they are
835+ if trimmed_src. starts_with ( "//" ) || trimmed_src. is_empty ( ) {
836+ if !trimmed_src. is_empty ( ) {
837+ // Match the whitespace of the incoming source line
838+ for s in line. chars ( ) . take_while ( |c| c. is_whitespace ( ) ) {
839+ output. push ( s) ;
840+ }
841+
842+ // Bump out the indent level if the line starts with a closing brace (ie we're at the end of a block)
843+ if matches ! ( trimmed_pretty_line. chars( ) . next( ) , Some ( ')' | '}' | ']' ) ) {
844+ output. push_str ( self . out . indent . indent_str ( ) ) ;
845+ }
846+
847+ printed_empty_line = false ;
848+ output. push_str ( trimmed_src) ;
849+ output. push ( '\n' ) ;
850+ } else if !printed_empty_line {
851+ output. push ( '\n' ) ;
852+ printed_empty_line = true ;
853+ }
854+
855+ _ = source_lines. next ( ) ;
856+ continue ;
857+ }
858+
859+ let compacted_src_line = src. replace ( " " , "" ) . replace ( "," , "" ) ;
860+
861+ // If this source line matches our pretty line, we stop pulling down
862+ if compacted_src_line. contains ( & compacted_pretty_line) {
863+ break ;
864+ }
865+
866+ // Otherwise, consume this source line and keep going
867+ _ = source_lines. next ( ) ;
868+ }
869+
870+ // Once all whitespace is written, write the pretty line
871+ output. push_str ( line) ;
872+ printed_empty_line = false ;
873+
874+ // And then pull the corresponding source line
875+ let source_line = source_lines. next ( ) ;
876+
877+ // And then write any inline comments
878+ if let Some ( source_line) = source_line {
879+ if let Some ( captures) = COMMENT_REGEX . with ( |f| f. captures ( source_line) ) {
880+ if let Some ( comment) = captures. get ( 1 ) {
881+ output. push_str ( " // " ) ;
882+ output. push_str ( comment. as_str ( ) . replace ( "//" , "" ) . trim ( ) ) ;
883+ }
884+ }
885+ }
886+ }
887+ }
888+
889+ self . write_mulitiline_tokens ( output) ?;
802890
803891 Ok ( ( ) )
804892 }
@@ -815,7 +903,10 @@ impl<'a> Writer<'a> {
815903 writeln ! ( self . out, "{first}" ) ?;
816904
817905 while let Some ( line) = lines. next ( ) {
818- self . out . tab ( ) ?;
906+ if !line. trim ( ) . is_empty ( ) {
907+ self . out . tab ( ) ?;
908+ }
909+
819910 write ! ( self . out, "{line}" ) ?;
820911 if lines. peek ( ) . is_none ( ) {
821912 write ! ( self . out, "" ) ?;
0 commit comments