From 57bcabc1082c948e2cfda3f005c41d8236ead7a4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 19 Apr 2018 17:46:13 +0200 Subject: [PATCH] Generate alias file --- src/librustdoc/html/item_type.rs | 2 +- src/librustdoc/html/layout.rs | 1 + src/librustdoc/html/render.rs | 80 +++++++++++++++++++++++++++++--- src/libstd/lib.rs | 1 + src/libstd/primitive_docs.rs | 3 ++ src/libsyntax/feature_gate.rs | 7 +++ 6 files changed, 87 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index e9c6488c49c..537828de2c7 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -19,7 +19,7 @@ use clean; /// discriminants. JavaScript then is used to decode them into the original value. /// Consequently, every change to this type should be synchronized to /// the `itemTypes` mapping table in `static/main.js`. -#[derive(Copy, PartialEq, Clone)] +#[derive(Copy, PartialEq, Clone, Debug)] pub enum ItemType { Module = 0, ExternCrate = 1, diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 583c9f2b671..1880baeddf4 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -145,6 +145,7 @@ pub fn render( \ \ \ + \ \ ", css_extension = if css_file_extension { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 651319743aa..8fe8fe671dd 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -329,6 +329,10 @@ pub struct Cache { // yet when its implementation methods are being indexed. Caches such methods // and their parent id here and indexes them at the end of crate parsing. orphan_impl_items: Vec<(DefId, clean::Item)>, + + /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, + /// we need the alias element to have an array of items. + aliases: FxHashMap>, } /// Temporary storage for data obtained during `RustdocVisitor::clean()`. @@ -369,6 +373,7 @@ struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, } /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. +#[derive(Debug)] struct IndexItem { ty: ItemType, name: String, @@ -396,6 +401,7 @@ impl ToJson for IndexItem { } /// A type used for the search index. +#[derive(Debug)] struct Type { name: Option, generics: Option>, @@ -418,9 +424,10 @@ impl ToJson for Type { } /// Full type of functions/methods in the search index. +#[derive(Debug)] struct IndexItemFunctionType { inputs: Vec, - output: Option + output: Option, } impl ToJson for IndexItemFunctionType { @@ -609,6 +616,7 @@ pub fn run(mut krate: clean::Crate, owned_box_did, masked_crates: mem::replace(&mut krate.masked_crates, FxHashSet()), typarams: external_typarams, + aliases: FxHashMap(), }; // Cache where all our extern crates are located @@ -847,8 +855,7 @@ themePicker.onclick = function() {{ write(cx.dst.join("COPYRIGHT.txt"), include_bytes!("static/COPYRIGHT.txt"))?; - fn collect(path: &Path, krate: &str, - key: &str) -> io::Result> { + fn collect(path: &Path, krate: &str, key: &str) -> io::Result> { let mut ret = Vec::new(); if path.exists() { for line in BufReader::new(File::open(path)?).lines() { @@ -865,6 +872,36 @@ themePicker.onclick = function() {{ Ok(ret) } + fn show_item(item: &IndexItem, krate: &str) -> String { + format!("{{'crate':'{}','ty':'{}','name':'{}','path':'{}','parent':{}}}", + krate, item.ty, item.name, item.path, + if let Some(p) = item.parent_idx { p.to_string() } else { "null".to_owned() }) + } + + let dst = cx.dst.join("aliases.js"); + { + let mut all_aliases = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst); + let mut w = try_err!(File::create(&dst), &dst); + let mut output = String::with_capacity(100); + for (alias, items) in &cache.aliases { + if items.is_empty() { + continue + } + output.push_str(&format!("\"{}\":[{}],", + alias, + items.iter() + .map(|v| show_item(v, &krate.name)) + .collect::>() + .join(","))); + } + all_aliases.push(format!("ALIASES['{}'] = {{{}}};", krate.name, output)); + all_aliases.sort(); + try_err!(writeln!(&mut w, "var ALIASES = {{}};"), &dst); + for aliases in &all_aliases { + try_err!(writeln!(&mut w, "{}", aliases), &dst); + } + } + // Update the search index let dst = cx.dst.join("search-index.js"); let mut all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst); @@ -1251,13 +1288,13 @@ impl DocFolder for Cache { // `public_items` map, so we can skip inserting into the // paths map if there was already an entry present and we're // not a public item. - if - !self.paths.contains_key(&item.def_id) || - self.access_levels.is_public(item.def_id) + if !self.paths.contains_key(&item.def_id) || + self.access_levels.is_public(item.def_id) { self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } + self.add_aliases(&item); } // Link variants to their parent enum because pages aren't emitted // for each variant. @@ -1268,6 +1305,7 @@ impl DocFolder for Cache { } clean::PrimitiveItem(..) if item.visibility.is_some() => { + self.add_aliases(&item); self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } @@ -1372,6 +1410,36 @@ impl<'a> Cache { } } } + + fn add_aliases(&mut self, item: &clean::Item) { + if item.def_id.index == CRATE_DEF_INDEX { + return + } + if let Some(ref item_name) = item.name { + let path = self.paths.get(&item.def_id) + .map(|p| p.0.join("::").to_string()) + .unwrap_or("std".to_owned()); + for alias in item.attrs.lists("doc") + .filter(|a| a.check_name("alias")) + .filter_map(|a| a.value_str() + .map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::>() + .into_iter() { + self.aliases.entry(alias) + .or_insert(Vec::with_capacity(1)) + .push(IndexItem { + ty: item.type_(), + name: item_name.to_string(), + path: path.clone(), + desc: String::new(), + parent: None, + parent_idx: None, + search_type: get_index_search_type(&item), + }); + } + } + } } #[derive(Debug, Eq, PartialEq, Hash)] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 7d896695311..579fd0eaf3f 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -316,6 +316,7 @@ #![feature(doc_spotlight)] #![cfg_attr(test, feature(update_panic_count))] #![cfg_attr(windows, feature(used))] +#![feature(doc_alias)] #![default_lib_allocator] diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index ce4bbfffc2e..e2fcfb7c4b1 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -9,6 +9,8 @@ // except according to those terms. #[doc(primitive = "bool")] +#[doc(alias = "true")] +#[doc(alias = "false")] // /// The boolean type. /// @@ -68,6 +70,7 @@ mod prim_bool { } #[doc(primitive = "never")] +#[doc(alias = "!")] // /// The `!` type, also called "never". /// diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 6426c9a92f2..3f0a402c213 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -460,6 +460,9 @@ declare_features! ( (active, proc_macro_mod, "1.27.0", None, None), (active, proc_macro_expr, "1.27.0", None, None), (active, proc_macro_non_items, "1.27.0", None, None), + + // #[doc(alias = "...")] + (active, doc_alias, "1.27.0", None, None), ); declare_features! ( @@ -1455,6 +1458,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, doc_spotlight, attr.span, "#[doc(spotlight)] is experimental" ); + } else if content.iter().any(|c| c.check_name("alias")) { + gate_feature_post!(&self, doc_alias, attr.span, + "#[doc(alias = \"...\")] is experimental" + ); } } }