@@ -403,17 +403,29 @@ impl<'db> SemanticsImpl<'db> {
403403 )
404404 }
405405
406- pub fn resolve_offset_in_format_args (
406+ pub fn as_format_args_parts (
407407 & self ,
408- string : ast:: String ,
409- offset : TextSize ,
410- ) -> Option < ( TextRange , Option < PathResolution > ) > {
411- debug_assert ! ( offset <= string. syntax( ) . text_range( ) . len( ) ) ;
412- let literal = string. syntax ( ) . parent ( ) . filter ( |it| it. kind ( ) == SyntaxKind :: LITERAL ) ?;
413- let format_args = ast:: FormatArgsExpr :: cast ( literal. parent ( ) ?) ?;
414- let source_analyzer = & self . analyze_no_infer ( format_args. syntax ( ) ) ?;
415- let format_args = self . wrap_node_infile ( format_args) ;
416- source_analyzer. resolve_offset_in_format_args ( self . db , format_args. as_ref ( ) , offset)
408+ string : & ast:: String ,
409+ ) -> Option < Vec < ( TextRange , Option < PathResolution > ) > > {
410+ if let Some ( quote) = string. open_quote_text_range ( ) {
411+ return self
412+ . descend_into_macros ( DescendPreference :: SameText , string. syntax ( ) . clone ( ) )
413+ . into_iter ( )
414+ . find_map ( |token| {
415+ let string = ast:: String :: cast ( token) ?;
416+ let literal =
417+ string. syntax ( ) . parent ( ) . filter ( |it| it. kind ( ) == SyntaxKind :: LITERAL ) ?;
418+ let format_args = ast:: FormatArgsExpr :: cast ( literal. parent ( ) ?) ?;
419+ let source_analyzer = self . analyze_no_infer ( format_args. syntax ( ) ) ?;
420+ let format_args = self . wrap_node_infile ( format_args) ;
421+ let res = source_analyzer
422+ . as_format_args_parts ( self . db , format_args. as_ref ( ) ) ?
423+ . map ( |( range, res) | ( range + quote. end ( ) , res) )
424+ . collect ( ) ;
425+ Some ( res)
426+ } ) ;
427+ }
428+ None
417429 }
418430
419431 pub fn check_for_format_args_template (
@@ -438,6 +450,19 @@ impl<'db> SemanticsImpl<'db> {
438450 None
439451 }
440452
453+ fn resolve_offset_in_format_args (
454+ & self ,
455+ string : ast:: String ,
456+ offset : TextSize ,
457+ ) -> Option < ( TextRange , Option < PathResolution > ) > {
458+ debug_assert ! ( offset <= string. syntax( ) . text_range( ) . len( ) ) ;
459+ let literal = string. syntax ( ) . parent ( ) . filter ( |it| it. kind ( ) == SyntaxKind :: LITERAL ) ?;
460+ let format_args = ast:: FormatArgsExpr :: cast ( literal. parent ( ) ?) ?;
461+ let source_analyzer = & self . analyze_no_infer ( format_args. syntax ( ) ) ?;
462+ let format_args = self . wrap_node_infile ( format_args) ;
463+ source_analyzer. resolve_offset_in_format_args ( self . db , format_args. as_ref ( ) , offset)
464+ }
465+
441466 /// Maps a node down by mapping its first and last token down.
442467 pub fn descend_node_into_attributes < N : AstNode > ( & self , node : N ) -> SmallVec < [ N ; 1 ] > {
443468 // This might not be the correct way to do this, but it works for now
0 commit comments