@@ -20,19 +20,63 @@ use syn::{parse::Parser, Ident, Lit, Meta, NestedMeta};
2020fn full_path ( krate : & Crate , item : & Id ) -> Option < ( String , String ) > {
2121 let item_summary = krate. paths . get ( item) ?;
2222 let kind = & item_summary. kind ;
23- let kind_str = serde_json:: to_string ( kind) . ok ( ) ?;
23+ let kind_str = match kind {
24+ rustdoc_json_types:: ItemKind :: AssocConst => todo ! ( "assoc_const" ) ,
25+ rustdoc_json_types:: ItemKind :: AssocType => todo ! ( "assoc_type" ) ,
26+ rustdoc_json_types:: ItemKind :: Constant => "constant" ,
27+ rustdoc_json_types:: ItemKind :: Enum => "enum" ,
28+ rustdoc_json_types:: ItemKind :: ExternCrate => todo ! ( "extern_crate" ) ,
29+ rustdoc_json_types:: ItemKind :: ForeignType => todo ! ( "foreign_type" ) ,
30+ rustdoc_json_types:: ItemKind :: Function => "fn" ,
31+ rustdoc_json_types:: ItemKind :: Impl => todo ! ( "impl" ) ,
32+ rustdoc_json_types:: ItemKind :: Import => todo ! ( "import" ) ,
33+ rustdoc_json_types:: ItemKind :: Keyword => todo ! ( "keyword" ) ,
34+ rustdoc_json_types:: ItemKind :: Macro => "macro" ,
35+ rustdoc_json_types:: ItemKind :: Module => "index" ,
36+ rustdoc_json_types:: ItemKind :: OpaqueTy => todo ! ( "opaque_ty" ) ,
37+ rustdoc_json_types:: ItemKind :: Primitive => "primitive" ,
38+ rustdoc_json_types:: ItemKind :: ProcAttribute => todo ! ( "proc_attribute" ) ,
39+ rustdoc_json_types:: ItemKind :: ProcDerive => todo ! ( "proc_derive" ) ,
40+ rustdoc_json_types:: ItemKind :: Static => "static" ,
41+ rustdoc_json_types:: ItemKind :: Struct => "struct" ,
42+ rustdoc_json_types:: ItemKind :: StructField => todo ! ( "struct_field" ) ,
43+ rustdoc_json_types:: ItemKind :: Trait => "trait" ,
44+ rustdoc_json_types:: ItemKind :: TraitAlias => "trait_alias" ,
45+ rustdoc_json_types:: ItemKind :: Typedef => "type" ,
46+ rustdoc_json_types:: ItemKind :: Union => todo ! ( "union" ) ,
47+ rustdoc_json_types:: ItemKind :: Variant => {
48+ return Some ( ( item_summary. path . join ( "::" ) , specialcase_variant ( & item_summary. path ) ) ) ;
49+ }
50+ } ;
2451 let mut url = String :: from ( "https://doc.rust-lang.org/nightly/" ) ;
2552 let mut iter = item_summary. path . iter ( ) ;
26- iter. next_back ( ) ;
53+ if !matches ! ( kind, rustdoc_json_types:: ItemKind :: Module ) {
54+ iter. next_back ( ) ;
55+ }
2756 url. push_str ( & iter. cloned ( ) . collect :: < Vec < _ > > ( ) . join ( "/" ) ) ;
2857 url. push ( '/' ) ;
29- url. push_str ( kind_str. trim_matches ( '"' ) ) ;
30- url. push ( '.' ) ;
31- url. push_str ( item_summary. path . last ( ) . unwrap ( ) ) ;
58+ url. push_str ( kind_str) ;
59+ if !matches ! ( kind, rustdoc_json_types:: ItemKind :: Module ) {
60+ url. push ( '.' ) ;
61+ url. push_str ( item_summary. path . last ( ) . unwrap ( ) ) ;
62+ }
3263 url. push_str ( ".html" ) ;
3364 Some ( ( item_summary. path . join ( "::" ) , url) )
3465}
3566
67+ fn specialcase_variant ( path : & [ String ] ) -> String {
68+ let mut iter = path. iter ( ) ;
69+ let mut out = String :: from ( "https://doc.rust-lang.org/nightly/" ) ;
70+ let variant = iter. next_back ( ) ;
71+ let enum_name = iter. next_back ( ) ;
72+ out. push_str ( & iter. cloned ( ) . collect :: < Vec < _ > > ( ) . join ( "/" ) ) ;
73+ out. push_str ( "/enum." ) ;
74+ out. push_str ( enum_name. unwrap ( ) ) ;
75+ out. push_str ( ".html#variant." ) ;
76+ out. push_str ( variant. unwrap ( ) ) ;
77+ out
78+ }
79+
3680fn is_ident ( ident : & Ident , name : & str ) -> bool {
3781 * ident == Ident :: new ( name, ident. span ( ) )
3882}
@@ -41,6 +85,20 @@ fn is_ident(ident: &Ident, name: &str) -> bool {
4185pub fn load_rustdoc_json_metadata ( doc_dir : & Path ) -> HashMap < String , Vec < ( String , String ) > > {
4286 let mut all_items = HashMap :: new ( ) ;
4387
88+ // Given a `NestedMeta` like `feature = "xyz"`, returns `xyz`.
89+ let get_feature_name = |nested : & _ | match nested {
90+ NestedMeta :: Meta ( Meta :: NameValue ( name_value) ) => {
91+ if !is_ident ( name_value. path . get_ident ( ) ?, "feature" ) {
92+ return None ;
93+ }
94+ match & name_value. lit {
95+ Lit :: Str ( s) => Some ( s. value ( ) ) ,
96+ _ => None ,
97+ }
98+ }
99+ _ => None ,
100+ } ;
101+
44102 for file in fs:: read_dir ( doc_dir) . expect ( "failed to list files in directory" ) {
45103 let entry = file. expect ( "failed to list file in directory" ) ;
46104 let file = fs:: File :: open ( entry. path ( ) ) . expect ( "failed to open file" ) ;
@@ -53,41 +111,26 @@ pub fn load_rustdoc_json_metadata(doc_dir: &Path) -> HashMap<String, Vec<(String
53111 continue ;
54112 }
55113 let unstable_feature = item. attrs . iter ( ) . find_map ( |attr : & String | {
56- let Ok ( parsed) = syn:: Attribute :: parse_outer. parse_str ( attr) . map ( |mut v| v. swap_remove ( 0 ) ) else { return None } ;
114+ let Ok ( parseable) = syn:: Attribute :: parse_outer. parse_str ( attr) else { return None ; } ;
115+ for parsed in parseable {
116+ let Some ( ident) = parsed. path . get_ident ( ) else { continue ; } ;
117+ // Make sure this is an `unstable` attribute.
118+ if !is_ident ( ident, "unstable" ) {
119+ continue ;
120+ }
57121
58- // Make sure this is an `unstable` attribute.
59- if !is_ident ( parsed. path . get_ident ( ) ?, "unstable" ) {
60- return None ;
61- }
122+ // Given `#[unstable(feature = "xyz")]`, return `(feature = "xyz")`.
123+ let list = match parsed. parse_meta ( ) {
124+ Ok ( Meta :: List ( list) ) => list,
125+ _ => continue ,
126+ } ;
62127
63- // Given `#[unstable(feature = "xyz")]`, return `(feature = "xyz")`.
64- let list = match parsed. parse_meta ( ) {
65- Ok ( Meta :: List ( list) ) => list,
66- _ => return None ,
67- } ;
68-
69- // Given a `NestedMeta` like `feature = "xyz"`, returns `xyz`.
70- let get_feature_name = |nested : & _ | {
71- match nested {
72- NestedMeta :: Meta ( Meta :: NameValue ( name_value) ) => {
73- if !is_ident ( name_value. path . get_ident ( ) ?, "feature" ) {
74- return None ;
75- }
76- match & name_value. lit {
77- Lit :: Str ( s) => Some ( s. value ( ) ) ,
78- _ => None ,
79- }
128+ for nested in list. nested . iter ( ) {
129+ if let Some ( feat) = get_feature_name ( nested) {
130+ return Some ( feat) ;
80131 }
81- _ => None ,
82- }
83- } ;
84-
85- for nested in list. nested . iter ( ) {
86- if let Some ( feat) = get_feature_name ( nested) {
87- return Some ( feat) ;
88132 }
89133 }
90-
91134 None
92135 } ) ;
93136 if let Some ( feat) = unstable_feature {
0 commit comments