@@ -24,7 +24,8 @@ use std::ops::Range;
2424
2525use core:: DocContext ;
2626use fold:: DocFolder ;
27- use html:: markdown:: markdown_links;
27+ use html:: markdown:: { find_testable_code, markdown_links, ErrorCodes , LangString } ;
28+
2829use passes:: Pass ;
2930
3031pub const COLLECT_INTRA_DOC_LINKS : Pass =
@@ -56,13 +57,15 @@ enum PathKind {
5657struct LinkCollector < ' a , ' tcx : ' a , ' rcx : ' a , ' cstore : ' rcx > {
5758 cx : & ' a DocContext < ' a , ' tcx , ' rcx , ' cstore > ,
5859 mod_ids : Vec < NodeId > ,
60+ is_nightly_build : bool ,
5961}
6062
6163impl < ' a , ' tcx , ' rcx , ' cstore > LinkCollector < ' a , ' tcx , ' rcx , ' cstore > {
6264 fn new ( cx : & ' a DocContext < ' a , ' tcx , ' rcx , ' cstore > ) -> Self {
6365 LinkCollector {
6466 cx,
6567 mod_ids : Vec :: new ( ) ,
68+ is_nightly_build : UnstableFeatures :: from_environment ( ) . is_nightly_build ( ) ,
6669 }
6770 }
6871
@@ -211,6 +214,43 @@ impl<'a, 'tcx, 'rcx, 'cstore> LinkCollector<'a, 'tcx, 'rcx, 'cstore> {
211214 }
212215}
213216
217+ fn look_for_tests < ' a , ' tcx : ' a , ' rcx : ' a , ' cstore : ' rcx > (
218+ cx : & ' a DocContext < ' a , ' tcx , ' rcx , ' cstore > ,
219+ dox : & str ,
220+ item : & Item ,
221+ ) {
222+ if ( item. is_mod ( ) && cx. tcx . hir . as_local_node_id ( item. def_id ) . is_none ( ) ) ||
223+ cx. as_local_node_id ( item. def_id ) . is_none ( ) {
224+ // If non-local, no need to check anything.
225+ return ;
226+ }
227+
228+ struct Tests {
229+ found_tests : usize ,
230+ }
231+
232+ impl :: test:: Tester for Tests {
233+ fn add_test ( & mut self , _: String , _: LangString , _: usize ) {
234+ self . found_tests += 1 ;
235+ }
236+ }
237+
238+ let mut tests = Tests {
239+ found_tests : 0 ,
240+ } ;
241+
242+ if find_testable_code ( & dox, & mut tests, ErrorCodes :: No ) . is_ok ( ) {
243+ if tests. found_tests == 0 {
244+ let mut diag = cx. tcx . struct_span_lint_node (
245+ lint:: builtin:: MISSING_DOC_CODE_EXAMPLES ,
246+ NodeId :: new ( 0 ) ,
247+ span_of_attrs ( & item. attrs ) ,
248+ "Missing code example in this documentation" ) ;
249+ diag. emit ( ) ;
250+ }
251+ }
252+ }
253+
214254impl < ' a , ' tcx , ' rcx , ' cstore > DocFolder for LinkCollector < ' a , ' tcx , ' rcx , ' cstore > {
215255 fn fold_item ( & mut self , mut item : Item ) -> Option < Item > {
216256 let item_node_id = if item. is_mod ( ) {
@@ -273,6 +313,12 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for LinkCollector<'a, 'tcx, 'rcx, 'cstor
273313 let cx = self . cx ;
274314 let dox = item. attrs . collapsed_doc_value ( ) . unwrap_or_else ( String :: new) ;
275315
316+ look_for_tests ( & cx, & dox, & item) ;
317+
318+ if !self . is_nightly_build {
319+ return None ;
320+ }
321+
276322 for ( ori_link, link_range) in markdown_links ( & dox) {
277323 // bail early for real links
278324 if ori_link. contains ( '/' ) {
0 commit comments