@@ -403,17 +403,29 @@ impl<'db> SemanticsImpl<'db> {
403
403
)
404
404
}
405
405
406
- pub fn resolve_offset_in_format_args (
406
+ pub fn as_format_args_parts (
407
407
& 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
417
429
}
418
430
419
431
pub fn check_for_format_args_template (
@@ -438,6 +450,19 @@ impl<'db> SemanticsImpl<'db> {
438
450
None
439
451
}
440
452
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
+
441
466
/// Maps a node down by mapping its first and last token down.
442
467
pub fn descend_node_into_attributes < N : AstNode > ( & self , node : N ) -> SmallVec < [ N ; 1 ] > {
443
468
// This might not be the correct way to do this, but it works for now
0 commit comments