about summary refs log tree commit diff
path: root/src/librustdoc/html/render.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/html/render.rs')
-rw-r--r--src/librustdoc/html/render.rs220
1 files changed, 85 insertions, 135 deletions
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 4dd2a6562a4..f51f47a8d33 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -42,9 +42,6 @@ use std::rc::Rc;
 use std::str;
 use std::sync::Arc;
 
-use rustc::middle::privacy::AccessLevels;
-use rustc::middle::stability;
-use rustc_ast::ast;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -52,6 +49,8 @@ use rustc_feature::UnstableFeatures;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::Mutability;
+use rustc_middle::middle::privacy::AccessLevels;
+use rustc_middle::middle::stability;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::FileName;
@@ -59,8 +58,8 @@ use rustc_span::symbol::{sym, Symbol};
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
 
-use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy};
-use crate::config::RenderOptions;
+use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind};
+use crate::config::{OutputFormat, RenderOptions};
 use crate::docfs::{DocFS, ErrorStorage, PathError};
 use crate::doctree;
 use crate::html::escape::Escape;
@@ -270,6 +269,7 @@ pub struct RenderInfo {
     pub deref_trait_did: Option<DefId>,
     pub deref_mut_trait_did: Option<DefId>,
     pub owned_box_did: Option<DefId>,
+    pub output_format: Option<OutputFormat>,
 }
 
 // Helper structs for rendering items/sidebars and carrying along contextual
@@ -302,19 +302,25 @@ impl Serialize for IndexItem {
 
 /// A type used for the search index.
 #[derive(Debug)]
-struct Type {
+struct RenderType {
+    ty: Option<DefId>,
+    idx: Option<usize>,
     name: Option<String>,
-    generics: Option<Vec<String>>,
+    generics: Option<Vec<Generic>>,
 }
 
-impl Serialize for Type {
+impl Serialize for RenderType {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
         S: Serializer,
     {
         if let Some(name) = &self.name {
             let mut seq = serializer.serialize_seq(None)?;
-            seq.serialize_element(&name)?;
+            if let Some(id) = self.idx {
+                seq.serialize_element(&id)?;
+            } else {
+                seq.serialize_element(&name)?;
+            }
             if let Some(generics) = &self.generics {
                 seq.serialize_element(&generics)?;
             }
@@ -325,11 +331,32 @@ impl Serialize for Type {
     }
 }
 
+/// A type used for the search index.
+#[derive(Debug)]
+struct Generic {
+    name: String,
+    defid: Option<DefId>,
+    idx: Option<usize>,
+}
+
+impl Serialize for Generic {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        if let Some(id) = self.idx {
+            serializer.serialize_some(&id)
+        } else {
+            serializer.serialize_some(&self.name)
+        }
+    }
+}
+
 /// Full type of functions/methods in the search index.
 #[derive(Debug)]
 struct IndexItemFunctionType {
-    inputs: Vec<Type>,
-    output: Option<Vec<Type>>,
+    inputs: Vec<TypeWithKind>,
+    output: Option<Vec<TypeWithKind>>,
 }
 
 impl Serialize for IndexItemFunctionType {
@@ -340,8 +367,8 @@ impl Serialize for IndexItemFunctionType {
         // If we couldn't figure out a type, just write `null`.
         let mut iter = self.inputs.iter();
         if match self.output {
-            Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
-            None => iter.any(|ref i| i.name.is_none()),
+            Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()),
+            None => iter.any(|ref i| i.ty.name.is_none()),
         } {
             serializer.serialize_none()
         } else {
@@ -359,6 +386,31 @@ impl Serialize for IndexItemFunctionType {
     }
 }
 
+#[derive(Debug)]
+pub struct TypeWithKind {
+    ty: RenderType,
+    kind: TypeKind,
+}
+
+impl From<(RenderType, TypeKind)> for TypeWithKind {
+    fn from(x: (RenderType, TypeKind)) -> TypeWithKind {
+        TypeWithKind { ty: x.0, kind: x.1 }
+    }
+}
+
+impl Serialize for TypeWithKind {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        let mut seq = serializer.serialize_seq(None)?;
+        seq.serialize_element(&self.ty.name)?;
+        let x: ItemType = self.kind.into();
+        seq.serialize_element(&x)?;
+        seq.end()
+    }
+}
+
 thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
 thread_local!(pub static CURRENT_DEPTH: Cell<usize> = Cell::new(0));
 
@@ -730,7 +782,7 @@ themePicker.onblur = handleThemeButtonsBlur;
                         .split('"')
                         .next()
                         .map(|s| s.to_owned())
-                        .unwrap_or_else(|| String::new()),
+                        .unwrap_or_else(String::new),
                 );
             }
         }
@@ -1542,7 +1594,7 @@ impl Context {
         }
 
         if self.shared.sort_modules_alphabetically {
-            for (_, items) in &mut map {
+            for items in map.values_mut() {
                 items.sort();
             }
         }
@@ -1565,7 +1617,7 @@ impl Context {
 
         let mut path = String::new();
 
-        // We can safely ignore macros from other libraries
+        // We can safely ignore synthetic `SourceFile`s.
         let file = match item.source.filename {
             FileName::Real(ref path) => path,
             _ => return None,
@@ -2106,7 +2158,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
                     docs = MarkdownSummaryLine(doc_value, &myitem.links()).to_string(),
                     class = myitem.type_(),
                     add = add,
-                    stab = stab.unwrap_or_else(|| String::new()),
+                    stab = stab.unwrap_or_else(String::new),
                     unsafety_flag = unsafety_flag,
                     href = item_path(myitem.type_(), myitem.name.as_ref().unwrap()),
                     title = [full_path(cx, myitem), myitem.type_().to_string()]
@@ -2325,7 +2377,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
         f.generics.print()
     )
     .len();
-    write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it));
+    write!(w, "<pre class='rust fn'>");
     render_attributes(w, it, false);
     write!(
         w,
@@ -2528,13 +2580,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
         let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-        write!(
-            w,
-            "<h3 id='{id}' class='method'>{extra}<code id='{ns_id}'>",
-            extra = render_spotlight_traits(m),
-            id = id,
-            ns_id = ns_id
-        );
+        write!(w, "<h3 id='{id}' class='method'><code id='{ns_id}'>", id = id, ns_id = ns_id);
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
         write!(w, "</code>");
         render_stability_since(w, m, t);
@@ -2727,7 +2773,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>) -> String {
     let name = it.name.as_ref().unwrap();
     let ty = match it.type_() {
         Typedef | AssocType => AssocType,
-        s @ _ => s,
+        s => s,
     };
 
     let anchor = format!("#{}.{}", ty, name);
@@ -3131,26 +3177,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
-    let path = pprust::path_to_string(&attr.path);
-
-    if attr.is_word() {
-        Some(path)
-    } else if let Some(v) = attr.value_str() {
-        Some(format!("{} = {:?}", path, v))
-    } else if let Some(values) = attr.meta_item_list() {
-        let display: Vec<_> = values
-            .iter()
-            .filter_map(|attr| attr.meta_item().and_then(|mi| render_attribute(mi)))
-            .collect();
-
-        if !display.is_empty() { Some(format!("{}({})", path, display.join(", "))) } else { None }
-    } else {
-        None
-    }
-}
-
-const ATTRIBUTE_WHITELIST: &'static [Symbol] = &[
+const ATTRIBUTE_WHITELIST: &[Symbol] = &[
     sym::export_name,
     sym::lang,
     sym::link_section,
@@ -3175,9 +3202,8 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) {
         if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty()) {
             continue;
         }
-        if let Some(s) = render_attribute(&attr.meta().unwrap()) {
-            attrs.push_str(&format!("#[{}]\n", s));
-        }
+
+        attrs.push_str(&pprust::attribute_to_string(&attr));
     }
     if !attrs.is_empty() {
         write!(
@@ -3401,10 +3427,8 @@ fn render_assoc_items(
         let deref_impl =
             traits.iter().find(|t| t.inner_impl().trait_.def_id() == c.deref_trait_did);
         if let Some(impl_) = deref_impl {
-            let has_deref_mut = traits
-                .iter()
-                .find(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did)
-                .is_some();
+            let has_deref_mut =
+                traits.iter().any(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did);
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
         }
 
@@ -3520,76 +3544,6 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
     }
 }
 
-fn render_spotlight_traits(item: &clean::Item) -> String {
-    match item.inner {
-        clean::FunctionItem(clean::Function { ref decl, .. })
-        | clean::TyMethodItem(clean::TyMethod { ref decl, .. })
-        | clean::MethodItem(clean::Method { ref decl, .. })
-        | clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl),
-        _ => String::new(),
-    }
-}
-
-fn spotlight_decl(decl: &clean::FnDecl) -> String {
-    let mut out = Buffer::html();
-    let mut trait_ = String::new();
-
-    if let Some(did) = decl.output.def_id() {
-        let c = cache();
-        if let Some(impls) = c.impls.get(&did) {
-            for i in impls {
-                let impl_ = i.inner_impl();
-                if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
-                    if out.is_empty() {
-                        out.push_str(&format!(
-                            "<h3 class=\"important\">Important traits for {}</h3>\
-                                      <code class=\"content\">",
-                            impl_.for_.print()
-                        ));
-                        trait_.push_str(&impl_.for_.print().to_string());
-                    }
-
-                    //use the "where" class here to make it small
-                    out.push_str(&format!(
-                        "<span class=\"where fmt-newline\">{}</span>",
-                        impl_.print()
-                    ));
-                    let t_did = impl_.trait_.def_id().unwrap();
-                    for it in &impl_.items {
-                        if let clean::TypedefItem(ref tydef, _) = it.inner {
-                            out.push_str("<span class=\"where fmt-newline\">    ");
-                            assoc_type(
-                                &mut out,
-                                it,
-                                &[],
-                                Some(&tydef.type_),
-                                AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
-                                "",
-                            );
-                            out.push_str(";</span>");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    if !out.is_empty() {
-        out.insert_str(
-            0,
-            &format!(
-                "<div class=\"important-traits\"><div class='tooltip'>ⓘ\
-                                    <span class='tooltiptext'>Important traits for {}</span></div>\
-                                    <div class=\"content hidden\">",
-                trait_
-            ),
-        );
-        out.push_str("</code></div></div>");
-    }
-
-    out.into_inner()
-}
-
 fn render_impl(
     w: &mut Buffer,
     cx: &Context,
@@ -3601,7 +3555,7 @@ fn render_impl(
     use_absolute: Option<bool>,
     is_on_foreign_type: bool,
     show_default_items: bool,
-    // This argument is used to reference same type with different pathes to avoid duplication
+    // This argument is used to reference same type with different paths to avoid duplication
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
 ) {
@@ -3696,14 +3650,13 @@ fn render_impl(
                 (true, " hidden")
             };
         match item.inner {
-            clean::MethodItem(clean::Method { ref decl, .. })
-            | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => {
+            clean::MethodItem(clean::Method { .. })
+            | clean::TyMethodItem(clean::TyMethod { .. }) => {
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
                     let id = cx.derive_id(format!("{}.{}", item_type, name));
                     let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                     write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
-                    write!(w, "{}", spotlight_decl(decl));
                     write!(w, "<code id='{}'>", ns_id);
                     render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
                     write!(w, "</code>");
@@ -3816,7 +3769,7 @@ fn render_impl(
     ) {
         for trait_item in &t.items {
             let n = trait_item.name.clone();
-            if i.items.iter().find(|m| m.name == n).is_some() {
+            if i.items.iter().any(|m| m.name == n) {
                 continue;
             }
             let did = i.trait_.as_ref().unwrap().def_id().unwrap();
@@ -4610,7 +4563,7 @@ fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) {
     document(w, cx, it)
 }
 
-crate const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang";
+crate const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";
 
 fn make_item_keywords(it: &clean::Item) -> String {
     format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap())
@@ -4640,12 +4593,9 @@ fn collect_paths_for_type(first_ty: clean::Type) -> Vec<String> {
                 let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone());
                 let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern);
 
-                match fqp {
-                    Some(path) => {
-                        out.push(path.join("::"));
-                    }
-                    _ => {}
-                };
+                if let Some(path) = fqp {
+                    out.push(path.join("::"));
+                }
             }
             clean::Type::Tuple(tys) => {
                 work.extend(tys.into_iter());