@@ -47,6 +47,7 @@ pub struct AnnotateSnippetEmitter {
4747 track_diagnostics : bool ,
4848 terminal_url : TerminalUrl ,
4949 theme : OutputTheme ,
50+ show_suggestions_with_unavailable_source : bool ,
5051}
5152
5253impl Debug for AnnotateSnippetEmitter {
@@ -63,6 +64,10 @@ impl Debug for AnnotateSnippetEmitter {
6364 . field ( "track_diagnostics" , & self . track_diagnostics )
6465 . field ( "terminal_url" , & self . terminal_url )
6566 . field ( "theme" , & self . theme )
67+ . field (
68+ "show_suggestions_with_unavailable_source" ,
69+ & self . show_suggestions_with_unavailable_source ,
70+ )
6671 . finish ( )
6772 }
6873}
@@ -136,6 +141,7 @@ impl AnnotateSnippetEmitter {
136141 track_diagnostics : false ,
137142 terminal_url : TerminalUrl :: No ,
138143 theme : OutputTheme :: Ascii ,
144+ show_suggestions_with_unavailable_source : false ,
139145 }
140146 }
141147
@@ -307,6 +313,11 @@ impl AnnotateSnippetEmitter {
307313 SuggestionStyle :: HideCodeInline
308314 | SuggestionStyle :: ShowCode
309315 | SuggestionStyle :: ShowAlways => {
316+ let unavailable_source_span = if self . show_suggestions_with_unavailable_source {
317+ self . suggestion_span_with_unavailable_source ( sm, & suggestion)
318+ } else {
319+ None
320+ } ;
310321 let substitutions = suggestion
311322 . substitutions
312323 . into_iter ( )
@@ -341,8 +352,19 @@ impl AnnotateSnippetEmitter {
341352 return None ;
342353 }
343354
344- // We can't splice anything if the source is unavailable.
345- if !sm. ensure_source_file_source_present ( & lo_file) {
355+ // We can't splice anything if the source is unavailable. When the
356+ // span-only fallback is enabled, also avoid rendering source that was
357+ // intentionally hidden from diagnostics.
358+ let can_show_source = if self . show_suggestions_with_unavailable_source {
359+ should_show_source_code (
360+ & self . ignored_directories_in_source_blocks ,
361+ sm,
362+ & lo_file,
363+ )
364+ } else {
365+ sm. ensure_source_file_source_present ( & lo_file)
366+ } ;
367+ if !can_show_source {
346368 return None ;
347369 }
348370
@@ -356,6 +378,30 @@ impl AnnotateSnippetEmitter {
356378 . collect :: < Vec < _ > > ( ) ;
357379
358380 if substitutions. is_empty ( ) {
381+ if let Some ( span) = unavailable_source_span {
382+ let msg = format_diag_message ( & suggestion. msg , args) . to_string ( ) ;
383+ report. push ( std:: mem:: replace (
384+ & mut group,
385+ Group :: with_title (
386+ annotate_snippets:: Level :: HELP . secondary_title ( msg) ,
387+ ) ,
388+ ) ) ;
389+
390+ let file_ann = collect_annotations ( args, & span, sm) ;
391+ let level = annotate_snippets:: Level :: HELP ;
392+ for ( file_idx, ( file, annotations) ) in file_ann. into_iter ( ) . enumerate ( )
393+ {
394+ group = self . unannotated_messages (
395+ annotations,
396+ & file. name ,
397+ sm,
398+ file_idx,
399+ & mut report,
400+ group,
401+ & level,
402+ ) ;
403+ }
404+ }
359405 continue ;
360406 }
361407 let mut msg = format_diag_message ( & suggestion. msg , args) . to_string ( ) ;
@@ -645,6 +691,36 @@ impl AnnotateSnippetEmitter {
645691 }
646692 group
647693 }
694+
695+ fn suggestion_span_with_unavailable_source (
696+ & self ,
697+ sm : & Arc < SourceMap > ,
698+ suggestion : & CodeSuggestion ,
699+ ) -> Option < MultiSpan > {
700+ let spans = suggestion
701+ . substitutions
702+ . iter ( )
703+ . flat_map ( |subst| & subst. parts )
704+ . filter_map ( |part| {
705+ if sm. is_valid_span ( part. span ) . is_err ( ) {
706+ debug ! ( "suggestion contains an invalid span: {:?}" , part) ;
707+ return None ;
708+ }
709+ let lines = sm. span_to_lines ( part. span ) . ok ( ) ?;
710+ if should_show_source_code (
711+ & self . ignored_directories_in_source_blocks ,
712+ sm,
713+ & lines. file ,
714+ ) {
715+ None
716+ } else {
717+ Some ( part. span )
718+ }
719+ } )
720+ . collect :: < Vec < _ > > ( ) ;
721+
722+ if spans. is_empty ( ) { None } else { Some ( MultiSpan :: from_spans ( spans) ) }
723+ }
648724}
649725
650726fn emit_to_destination (
0 commit comments