@@ -759,6 +759,67 @@ pub fn expand_past_previous_comma(sess: &impl HasSession, span: Span) -> Span {
759759 extended. with_lo ( extended. lo ( ) - BytePos ( 1 ) )
760760}
761761
762+ /// Expand a span to include a preceding comma (not in comment) after `begin_pos`.
763+ /// ```rust,ignore
764+ /// writeln!(o, /* , */ "") -> writeln!(o, /* , */ "")
765+ /// ^^ ^^^^^^^^^^^^
766+ /// ```
767+ pub fn expand_past_previous_comma_after_begin_pos (
768+ sess : & impl HasSession ,
769+ span : Span ,
770+ begin_pos : BytePos ,
771+ ) -> Option < Span > {
772+ if span. lo ( ) <= begin_pos {
773+ return None ;
774+ }
775+
776+ let source_map = sess. sess ( ) . source_map ( ) ;
777+ let search_span = span. shrink_to_lo ( ) . with_lo ( begin_pos) ;
778+ let Ok ( text) = source_map. span_to_snippet ( search_span) else {
779+ return None ;
780+ } ;
781+
782+ let mut byte_offset = 0 ;
783+ for token in tokenize ( & text, FrontmatterAllowed :: No ) {
784+ if token. kind == TokenKind :: Comma {
785+ let comma_end_pos =
786+ span. lo ( ) - BytePos ( u32:: try_from ( text. len ( ) ) . expect ( "Error casting from usize to u32" ) - byte_offset) ;
787+ return Some ( span. with_lo ( comma_end_pos) ) ;
788+ }
789+ byte_offset += token. len ;
790+ }
791+
792+ None
793+ }
794+
795+ /// Expand a span to include the following comma (not in comment) before `end_pos`.
796+ /// ```rust,ignore
797+ /// println!("" /* , */ ,) -> println!("" /* , */ ,)
798+ /// ^^ ^^^^^^^^^^^^
799+ /// ```
800+ pub fn expand_past_next_comma_before_end_pos ( sess : & impl HasSession , span : Span , end_pos : BytePos ) -> Option < Span > {
801+ if span. hi ( ) >= end_pos {
802+ return None ;
803+ }
804+
805+ let source_map = sess. sess ( ) . source_map ( ) ;
806+ let search_span = span. shrink_to_hi ( ) . with_hi ( end_pos) ;
807+ let Ok ( text) = source_map. span_to_snippet ( search_span) else {
808+ return None ;
809+ } ;
810+
811+ let mut byte_offset = 0 ;
812+ for token in tokenize ( & text, FrontmatterAllowed :: No ) {
813+ if token. kind == TokenKind :: Comma {
814+ let comma_end_pos = span. hi ( ) + BytePos ( byte_offset + token. len ) ;
815+ return Some ( span. with_hi ( comma_end_pos) ) ;
816+ }
817+ byte_offset += token. len ;
818+ }
819+
820+ None
821+ }
822+
762823/// Converts `expr` to a `char` literal if it's a `str` literal containing a single
763824/// character (or a single byte with `ascii_only`)
764825pub fn str_literal_to_char_literal (
0 commit comments