1
Fork 0

Generate alias file

This commit is contained in:
Guillaume Gomez 2018-04-19 17:46:13 +02:00
parent 654cb84852
commit 57bcabc108
6 changed files with 87 additions and 7 deletions

View file

@ -19,7 +19,7 @@ use clean;
/// discriminants. JavaScript then is used to decode them into the original value. /// discriminants. JavaScript then is used to decode them into the original value.
/// Consequently, every change to this type should be synchronized to /// Consequently, every change to this type should be synchronized to
/// the `itemTypes` mapping table in `static/main.js`. /// the `itemTypes` mapping table in `static/main.js`.
#[derive(Copy, PartialEq, Clone)] #[derive(Copy, PartialEq, Clone, Debug)]
pub enum ItemType { pub enum ItemType {
Module = 0, Module = 0,
ExternCrate = 1, ExternCrate = 1,

View file

@ -145,6 +145,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
</script>\ </script>\
<script src=\"{root_path}main{suffix}.js\"></script>\ <script src=\"{root_path}main{suffix}.js\"></script>\
<script defer src=\"{root_path}search-index.js\"></script>\ <script defer src=\"{root_path}search-index.js\"></script>\
<script defer src=\"{root_path}aliases.js\"></script>\
</body>\ </body>\
</html>", </html>",
css_extension = if css_file_extension { css_extension = if css_file_extension {

View file

@ -329,6 +329,10 @@ pub struct Cache {
// yet when its implementation methods are being indexed. Caches such methods // 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. // and their parent id here and indexes them at the end of crate parsing.
orphan_impl_items: Vec<(DefId, clean::Item)>, 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<String, Vec<IndexItem>>,
} }
/// Temporary storage for data obtained during `RustdocVisitor::clean()`. /// 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 /// 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. /// by hand to a large JS file at the end of cache-creation.
#[derive(Debug)]
struct IndexItem { struct IndexItem {
ty: ItemType, ty: ItemType,
name: String, name: String,
@ -396,6 +401,7 @@ impl ToJson for IndexItem {
} }
/// A type used for the search index. /// A type used for the search index.
#[derive(Debug)]
struct Type { struct Type {
name: Option<String>, name: Option<String>,
generics: Option<Vec<String>>, generics: Option<Vec<String>>,
@ -418,9 +424,10 @@ impl ToJson for Type {
} }
/// Full type of functions/methods in the search index. /// Full type of functions/methods in the search index.
#[derive(Debug)]
struct IndexItemFunctionType { struct IndexItemFunctionType {
inputs: Vec<Type>, inputs: Vec<Type>,
output: Option<Type> output: Option<Type>,
} }
impl ToJson for IndexItemFunctionType { impl ToJson for IndexItemFunctionType {
@ -609,6 +616,7 @@ pub fn run(mut krate: clean::Crate,
owned_box_did, owned_box_did,
masked_crates: mem::replace(&mut krate.masked_crates, FxHashSet()), masked_crates: mem::replace(&mut krate.masked_crates, FxHashSet()),
typarams: external_typarams, typarams: external_typarams,
aliases: FxHashMap(),
}; };
// Cache where all our extern crates are located // Cache where all our extern crates are located
@ -847,8 +855,7 @@ themePicker.onclick = function() {{
write(cx.dst.join("COPYRIGHT.txt"), write(cx.dst.join("COPYRIGHT.txt"),
include_bytes!("static/COPYRIGHT.txt"))?; include_bytes!("static/COPYRIGHT.txt"))?;
fn collect(path: &Path, krate: &str, fn collect(path: &Path, krate: &str, key: &str) -> io::Result<Vec<String>> {
key: &str) -> io::Result<Vec<String>> {
let mut ret = Vec::new(); let mut ret = Vec::new();
if path.exists() { if path.exists() {
for line in BufReader::new(File::open(path)?).lines() { for line in BufReader::new(File::open(path)?).lines() {
@ -865,6 +872,36 @@ themePicker.onclick = function() {{
Ok(ret) 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::<Vec<_>>()
.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 // Update the search index
let dst = cx.dst.join("search-index.js"); let dst = cx.dst.join("search-index.js");
let mut all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst); 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 // `public_items` map, so we can skip inserting into the
// paths map if there was already an entry present and we're // paths map if there was already an entry present and we're
// not a public item. // not a public item.
if if !self.paths.contains_key(&item.def_id) ||
!self.paths.contains_key(&item.def_id) ||
self.access_levels.is_public(item.def_id) self.access_levels.is_public(item.def_id)
{ {
self.paths.insert(item.def_id, self.paths.insert(item.def_id,
(self.stack.clone(), item.type_())); (self.stack.clone(), item.type_()));
} }
self.add_aliases(&item);
} }
// Link variants to their parent enum because pages aren't emitted // Link variants to their parent enum because pages aren't emitted
// for each variant. // for each variant.
@ -1268,6 +1305,7 @@ impl DocFolder for Cache {
} }
clean::PrimitiveItem(..) if item.visibility.is_some() => { clean::PrimitiveItem(..) if item.visibility.is_some() => {
self.add_aliases(&item);
self.paths.insert(item.def_id, (self.stack.clone(), self.paths.insert(item.def_id, (self.stack.clone(),
item.type_())); 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::<FxHashSet<_>>()
.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)] #[derive(Debug, Eq, PartialEq, Hash)]

View file

@ -316,6 +316,7 @@
#![feature(doc_spotlight)] #![feature(doc_spotlight)]
#![cfg_attr(test, feature(update_panic_count))] #![cfg_attr(test, feature(update_panic_count))]
#![cfg_attr(windows, feature(used))] #![cfg_attr(windows, feature(used))]
#![feature(doc_alias)]
#![default_lib_allocator] #![default_lib_allocator]

View file

@ -9,6 +9,8 @@
// except according to those terms. // except according to those terms.
#[doc(primitive = "bool")] #[doc(primitive = "bool")]
#[doc(alias = "true")]
#[doc(alias = "false")]
// //
/// The boolean type. /// The boolean type.
/// ///
@ -68,6 +70,7 @@
mod prim_bool { } mod prim_bool { }
#[doc(primitive = "never")] #[doc(primitive = "never")]
#[doc(alias = "!")]
// //
/// The `!` type, also called "never". /// The `!` type, also called "never".
/// ///

View file

@ -460,6 +460,9 @@ declare_features! (
(active, proc_macro_mod, "1.27.0", None, None), (active, proc_macro_mod, "1.27.0", None, None),
(active, proc_macro_expr, "1.27.0", None, None), (active, proc_macro_expr, "1.27.0", None, None),
(active, proc_macro_non_items, "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! ( declare_features! (
@ -1455,6 +1458,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
gate_feature_post!(&self, doc_spotlight, attr.span, gate_feature_post!(&self, doc_spotlight, attr.span,
"#[doc(spotlight)] is experimental" "#[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"
);
} }
} }
} }