@@ -12,6 +12,7 @@ use std::env;
12
12
use std:: ffi:: OsString ;
13
13
use std:: io:: prelude:: * ;
14
14
use std:: io;
15
+ use std:: mem;
15
16
use std:: path:: { Path , PathBuf } ;
16
17
use std:: panic:: { self , AssertUnwindSafe } ;
17
18
use std:: process:: Command ;
@@ -41,7 +42,7 @@ use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName};
41
42
use errors;
42
43
use errors:: emitter:: ColorConfig ;
43
44
44
- use clean:: Attributes ;
45
+ use clean:: { Attributes , AttributesExt , NestedAttributesExt } ;
45
46
use html:: markdown:: { self , ErrorCodes , LangString } ;
46
47
47
48
#[ derive( Clone , Default ) ]
@@ -51,6 +52,8 @@ pub struct TestOptions {
51
52
/// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
52
53
/// the default `#![allow(unused)]`.
53
54
pub display_warnings : bool ,
55
+ /// Whether to run doctests on private items.
56
+ pub document_private_items : bool ,
54
57
/// Additional crate-level attributes to add to doctests.
55
58
pub attrs : Vec < String > ,
56
59
}
@@ -65,7 +68,8 @@ pub fn run(input_path: &Path,
65
68
display_warnings : bool ,
66
69
linker : Option < PathBuf > ,
67
70
edition : Edition ,
68
- cg : CodegenOptions )
71
+ cg : CodegenOptions ,
72
+ document_private_items : bool )
69
73
-> isize {
70
74
let input = config:: Input :: File ( input_path. to_owned ( ) ) ;
71
75
@@ -124,6 +128,7 @@ pub fn run(input_path: &Path,
124
128
} ) ;
125
129
let mut opts = scrape_test_config ( hir_forest. krate ( ) ) ;
126
130
opts. display_warnings |= display_warnings;
131
+ opts. document_private_items |= document_private_items;
127
132
let mut collector = Collector :: new (
128
133
crate_name,
129
134
cfgs,
@@ -147,8 +152,9 @@ pub fn run(input_path: &Path,
147
152
collector : & mut collector,
148
153
map : & map,
149
154
codes : ErrorCodes :: from ( sess. opts . unstable_features . is_nightly_build ( ) ) ,
155
+ current_vis : true ,
150
156
} ;
151
- hir_collector. visit_testable ( "" . to_string ( ) , & krate. attrs , |this| {
157
+ hir_collector. visit_testable ( "" . to_string ( ) , & krate. attrs , true , |this| {
152
158
intravisit:: walk_crate ( this, krate) ;
153
159
} ) ;
154
160
}
@@ -169,9 +175,12 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
169
175
let mut opts = TestOptions {
170
176
no_crate_inject : false ,
171
177
display_warnings : false ,
178
+ document_private_items : false ,
172
179
attrs : Vec :: new ( ) ,
173
180
} ;
174
181
182
+ opts. document_private_items = krate. attrs . lists ( "doc" ) . has_word ( "document_private_items" ) ;
183
+
175
184
let test_attrs: Vec < _ > = krate. attrs . iter ( )
176
185
. filter ( |a| a. check_name ( "doc" ) )
177
186
. flat_map ( |a| a. meta_item_list ( ) . unwrap_or_else ( Vec :: new) )
@@ -664,12 +673,14 @@ struct HirCollector<'a, 'hir: 'a> {
664
673
collector : & ' a mut Collector ,
665
674
map : & ' a hir:: map:: Map < ' hir > ,
666
675
codes : ErrorCodes ,
676
+ current_vis : bool ,
667
677
}
668
678
669
679
impl < ' a , ' hir > HirCollector < ' a , ' hir > {
670
680
fn visit_testable < F : FnOnce ( & mut Self ) > ( & mut self ,
671
681
name : String ,
672
682
attrs : & [ ast:: Attribute ] ,
683
+ item_is_pub : bool ,
673
684
nested : F ) {
674
685
let mut attrs = Attributes :: from_ast ( self . sess . diagnostic ( ) , attrs) ;
675
686
if let Some ( ref cfg) = attrs. cfg {
@@ -678,6 +689,21 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
678
689
}
679
690
}
680
691
692
+ let old_vis = if attrs. has_doc_flag ( "hidden" ) {
693
+ Some ( mem:: replace ( & mut self . current_vis , false ) )
694
+ } else {
695
+ None
696
+ } ;
697
+
698
+ if !self . collector . opts . document_private_items {
699
+ if !( self . current_vis && item_is_pub) {
700
+ if let Some ( old_vis) = old_vis {
701
+ self . current_vis = old_vis;
702
+ }
703
+ return ;
704
+ }
705
+ }
706
+
681
707
let has_name = !name. is_empty ( ) ;
682
708
if has_name {
683
709
self . collector . names . push ( name) ;
@@ -698,6 +724,10 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
698
724
699
725
nested ( self ) ;
700
726
727
+ if let Some ( old_vis) = old_vis {
728
+ self . current_vis = old_vis;
729
+ }
730
+
701
731
if has_name {
702
732
self . collector . names . pop ( ) ;
703
733
}
@@ -710,31 +740,50 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
710
740
}
711
741
712
742
fn visit_item ( & mut self , item : & ' hir hir:: Item ) {
743
+ let is_public = item. vis . node . is_pub ( ) ;
744
+
713
745
let name = if let hir:: ItemKind :: Impl ( .., ref ty, _) = item. node {
714
746
self . map . node_to_pretty_string ( ty. id )
715
747
} else {
716
748
item. name . to_string ( )
717
749
} ;
718
750
719
- self . visit_testable ( name, & item. attrs , |this| {
751
+ let old_vis = if let hir:: ItemKind :: Mod ( ..) = item. node {
752
+ let old_vis = self . current_vis ;
753
+ self . current_vis &= is_public;
754
+ Some ( old_vis)
755
+ } else {
756
+ None
757
+ } ;
758
+
759
+ self . visit_testable ( name, & item. attrs , is_public, |this| {
720
760
intravisit:: walk_item ( this, item) ;
721
761
} ) ;
762
+
763
+ if let Some ( old_vis) = old_vis {
764
+ self . current_vis = old_vis;
765
+ }
722
766
}
723
767
724
768
fn visit_trait_item ( & mut self , item : & ' hir hir:: TraitItem ) {
725
- self . visit_testable ( item. ident . to_string ( ) , & item. attrs , |this| {
769
+ self . visit_testable ( item. ident . to_string ( ) , & item. attrs , true , |this| {
726
770
intravisit:: walk_trait_item ( this, item) ;
727
771
} ) ;
728
772
}
729
773
730
774
fn visit_impl_item ( & mut self , item : & ' hir hir:: ImplItem ) {
731
- self . visit_testable ( item. ident . to_string ( ) , & item. attrs , |this| {
775
+ let is_public = item. vis . node . is_pub ( ) ;
776
+ self . visit_testable ( item. ident . to_string ( ) , & item. attrs , is_public, |this| {
732
777
intravisit:: walk_impl_item ( this, item) ;
733
778
} ) ;
734
779
}
735
780
736
781
fn visit_foreign_item ( & mut self , item : & ' hir hir:: ForeignItem ) {
737
- self . visit_testable ( item. name . to_string ( ) , & item. attrs , |this| {
782
+ let is_public = item. vis . node . is_pub ( ) ;
783
+ self . visit_testable ( item. name . to_string ( ) ,
784
+ & item. attrs ,
785
+ is_public,
786
+ |this| {
738
787
intravisit:: walk_foreign_item ( this, item) ;
739
788
} ) ;
740
789
}
@@ -743,19 +792,25 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
743
792
v : & ' hir hir:: Variant ,
744
793
g : & ' hir hir:: Generics ,
745
794
item_id : ast:: NodeId ) {
746
- self . visit_testable ( v. node . name . to_string ( ) , & v. node . attrs , |this| {
795
+ self . visit_testable ( v. node . name . to_string ( ) , & v. node . attrs , true , |this| {
747
796
intravisit:: walk_variant ( this, v, g, item_id) ;
748
797
} ) ;
749
798
}
750
799
751
800
fn visit_struct_field ( & mut self , f : & ' hir hir:: StructField ) {
752
- self . visit_testable ( f. ident . to_string ( ) , & f. attrs , |this| {
801
+ let is_public = f. vis . node . is_pub ( ) ;
802
+ self . visit_testable ( f. ident . to_string ( ) ,
803
+ & f. attrs ,
804
+ is_public,
805
+ |this| {
753
806
intravisit:: walk_struct_field ( this, f) ;
754
807
} ) ;
755
808
}
756
809
757
810
fn visit_macro_def ( & mut self , macro_def : & ' hir hir:: MacroDef ) {
758
- self . visit_testable ( macro_def. name . to_string ( ) , & macro_def. attrs , |_| ( ) ) ;
811
+ // FIXME(misdreavus): does macro export status surface to us? is it in AccessLevels, does
812
+ // its #[macro_export] attribute show up here?
813
+ self . visit_testable ( macro_def. name . to_string ( ) , & macro_def. attrs , true , |_| ( ) ) ;
759
814
}
760
815
}
761
816
0 commit comments