Skip to content

Commit f2735b7

Browse files
Make the link generation work for more cases
1 parent 0dfc121 commit f2735b7

File tree

1 file changed

+78
-35
lines changed
  • src/tools/unstable-book-gen/src

1 file changed

+78
-35
lines changed

src/tools/unstable-book-gen/src/main.rs

+78-35
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,63 @@ use syn::{parse::Parser, Ident, Lit, Meta, NestedMeta};
2020
fn 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+
3680
fn 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 {
4185
pub 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

Comments
 (0)