@@ -57,6 +57,7 @@ use std::rc::Rc;
5757use std:: cell:: RefCell ;
5858use std:: sync:: Arc ;
5959use std:: u32;
60+ use std:: ops:: Range ;
6061
6162use core:: { self , DocContext } ;
6263use doctree;
@@ -954,12 +955,20 @@ fn type_ns_kind(def: Def, path_str: &str) -> (&'static str, &'static str, String
954955 ( kind, article, format ! ( "{}@{}" , kind, path_str) )
955956}
956957
958+ fn span_of_attrs ( attrs : & Attributes ) -> syntax_pos:: Span {
959+ if attrs. doc_strings . is_empty ( ) {
960+ return DUMMY_SP ;
961+ }
962+ let start = attrs. doc_strings [ 0 ] . span ( ) ;
963+ let end = attrs. doc_strings . last ( ) . unwrap ( ) . span ( ) ;
964+ start. to ( end)
965+ }
966+
957967fn ambiguity_error ( cx : & DocContext , attrs : & Attributes ,
958968 path_str : & str ,
959969 article1 : & str , kind1 : & str , disambig1 : & str ,
960970 article2 : & str , kind2 : & str , disambig2 : & str ) {
961- let sp = attrs. doc_strings . first ( )
962- . map_or ( DUMMY_SP , |a| a. span ( ) ) ;
971+ let sp = span_of_attrs ( attrs) ;
963972 cx. sess ( )
964973 . struct_span_warn ( sp,
965974 & format ! ( "`{}` is both {} {} and {} {}" ,
@@ -1174,8 +1183,39 @@ enum PathKind {
11741183 Type ,
11751184}
11761185
1177- fn resolution_failure ( cx : & DocContext , path_str : & str ) {
1178- cx. sess ( ) . warn ( & format ! ( "[{}] cannot be resolved, ignoring it..." , path_str) ) ;
1186+ fn resolution_failure (
1187+ cx : & DocContext ,
1188+ attrs : & Attributes ,
1189+ path_str : & str ,
1190+ dox : & str ,
1191+ link_range : Option < Range < usize > > ,
1192+ ) {
1193+ let sp = span_of_attrs ( attrs) ;
1194+ let mut diag = cx. sess ( )
1195+ . struct_span_warn ( sp, & format ! ( "[{}] cannot be resolved, ignoring it..." , path_str) ) ;
1196+
1197+ if let Some ( link_range) = link_range {
1198+ // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
1199+ // ^ ~~~~~~
1200+ // | link_range
1201+ // last_new_line_offset
1202+
1203+ let last_new_line_offset = dox[ ..link_range. start ] . rfind ( '\n' ) . map_or ( 0 , |n| n + 1 ) ;
1204+ let line = dox[ last_new_line_offset..] . lines ( ) . next ( ) . unwrap_or ( "" ) ;
1205+
1206+ // Print the line containing the `link_range` and manually mark it with '^'s
1207+ diag. note ( & format ! (
1208+ "the link appears in this line:\n \n {line}\n {indicator: <before$}{indicator:^<found$}" ,
1209+ line=line,
1210+ indicator="" ,
1211+ before=link_range. start - last_new_line_offset,
1212+ found=link_range. len( ) ,
1213+ ) ) ;
1214+ } else {
1215+
1216+ }
1217+
1218+ diag. emit ( ) ;
11791219}
11801220
11811221impl Clean < Attributes > for [ ast:: Attribute ] {
@@ -1184,7 +1224,7 @@ impl Clean<Attributes> for [ast::Attribute] {
11841224
11851225 if UnstableFeatures :: from_environment ( ) . is_nightly_build ( ) {
11861226 let dox = attrs. collapsed_doc_value ( ) . unwrap_or_else ( String :: new) ;
1187- for ori_link in markdown_links ( & dox) {
1227+ for ( ori_link, link_range ) in markdown_links ( & dox) {
11881228 // bail early for real links
11891229 if ori_link. contains ( '/' ) {
11901230 continue ;
@@ -1228,7 +1268,7 @@ impl Clean<Attributes> for [ast::Attribute] {
12281268 if let Ok ( def) = resolve ( cx, path_str, true ) {
12291269 def
12301270 } else {
1231- resolution_failure ( cx, path_str) ;
1271+ resolution_failure ( cx, & attrs , path_str, & dox , link_range ) ;
12321272 // this could just be a normal link or a broken link
12331273 // we could potentially check if something is
12341274 // "intra-doc-link-like" and warn in that case
@@ -1239,7 +1279,7 @@ impl Clean<Attributes> for [ast::Attribute] {
12391279 if let Ok ( def) = resolve ( cx, path_str, false ) {
12401280 def
12411281 } else {
1242- resolution_failure ( cx, path_str) ;
1282+ resolution_failure ( cx, & attrs , path_str, & dox , link_range ) ;
12431283 // this could just be a normal link
12441284 continue ;
12451285 }
@@ -1284,7 +1324,7 @@ impl Clean<Attributes> for [ast::Attribute] {
12841324 } else if let Ok ( value_def) = resolve ( cx, path_str, true ) {
12851325 value_def
12861326 } else {
1287- resolution_failure ( cx, path_str) ;
1327+ resolution_failure ( cx, & attrs , path_str, & dox , link_range ) ;
12881328 // this could just be a normal link
12891329 continue ;
12901330 }
@@ -1293,7 +1333,7 @@ impl Clean<Attributes> for [ast::Attribute] {
12931333 if let Some ( def) = macro_resolve ( cx, path_str) {
12941334 ( def, None )
12951335 } else {
1296- resolution_failure ( cx, path_str) ;
1336+ resolution_failure ( cx, & attrs , path_str, & dox , link_range ) ;
12971337 continue
12981338 }
12991339 }
0 commit comments