From 94630d4c8bbf4c7c7e680210cd5d5f848c53aeaa Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Sat, 29 Jun 2019 13:30:45 -0400 Subject: [PATCH] replace serialize with serde in rustdoc --- Cargo.lock | 2 + src/librustdoc/Cargo.toml | 2 + src/librustdoc/html/item_type.rs | 12 +++ src/librustdoc/html/render.rs | 143 +++++++++++++++++----------- src/librustdoc/html/render/cache.rs | 34 ++++--- src/librustdoc/lib.rs | 1 - 6 files changed, 125 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07a6c53c9c8..807304d11fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3924,6 +3924,8 @@ dependencies = [ "minifier", "pulldown-cmark 0.5.3", "rustc-rayon", + "serde", + "serde_json", "tempfile", ] diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index e3de7fe2049..f2822916d3c 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -12,4 +12,6 @@ path = "lib.rs" pulldown-cmark = { version = "0.5.3", default-features = false } minifier = "0.0.33" rayon = { version = "0.3.0", package = "rustc-rayon" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" tempfile = "3" diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index f5e45924893..85f132378b1 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -1,7 +1,11 @@ //! Item types. use std::fmt; + +use serde::{Serialize, Serializer}; + use syntax_pos::hygiene::MacroKind; + use crate::clean; /// Item type. Corresponds to `clean::ItemEnum` variants. @@ -45,6 +49,14 @@ pub enum ItemType { TraitAlias = 25, } +impl Serialize for ItemType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + (*self as u8).serialize(serializer) + } +} impl<'a> From<&'a clean::Item> for ItemType { fn from(item: &'a clean::Item) -> ItemType { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 86e5efbd7b3..e764b7ee527 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -31,7 +31,8 @@ use std::cmp::Ordering; use std::collections::{BTreeMap, VecDeque}; use std::default::Default; use std::error; -use std::fmt::{self, Formatter, Write as FmtWrite}; + +use std::fmt::{self, Formatter, Write}; use std::ffi::OsStr; use std::fs::{self, File}; use std::io::prelude::*; @@ -42,7 +43,8 @@ use std::sync::Arc; use std::rc::Rc; use errors; -use serialize::json::{ToJson, Json, as_json}; +use serde::{Serialize, Serializer}; +use serde::ser::SerializeSeq; use syntax::ast; use syntax::edition::Edition; use syntax::print::pprust; @@ -303,19 +305,22 @@ struct IndexItem { search_type: Option, } -impl ToJson for IndexItem { - fn to_json(&self) -> Json { +impl Serialize for IndexItem { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { assert_eq!(self.parent.is_some(), self.parent_idx.is_some()); - let mut data = Vec::with_capacity(6); - data.push((self.ty as usize).to_json()); - data.push(self.name.to_json()); - data.push(self.path.to_json()); - data.push(self.desc.to_json()); - data.push(self.parent_idx.to_json()); - data.push(self.search_type.to_json()); - - Json::Array(data) + ( + self.ty, + &self.name, + &self.path, + &self.desc, + self.parent_idx, + &self.search_type, + ) + .serialize(serializer) } } @@ -326,18 +331,20 @@ struct Type { generics: Option>, } -impl ToJson for Type { - fn to_json(&self) -> Json { - match self.name { - Some(ref name) => { - let mut data = Vec::with_capacity(2); - data.push(name.to_json()); - if let Some(ref generics) = self.generics { - data.push(generics.to_json()); - } - Json::Array(data) +impl Serialize for Type { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + if let Some(name) = &self.name { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&name)?; + if let Some(generics) = &self.generics { + seq.serialize_element(&generics)?; } - None => Json::Null, + seq.end() + } else { + serializer.serialize_none() } } } @@ -349,26 +356,29 @@ struct IndexItemFunctionType { output: Option>, } -impl ToJson for IndexItemFunctionType { - fn to_json(&self) -> Json { +impl Serialize for IndexItemFunctionType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { // 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()), } { - Json::Null + serializer.serialize_none() } else { - let mut data = Vec::with_capacity(2); - data.push(self.inputs.to_json()); - if let Some(ref output) = self.output { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.inputs)?; + if let Some(output) = &self.output { if output.len() > 1 { - data.push(output.to_json()); + seq.serialize_element(&output)?; } else { - data.push(output[0].to_json()); + seq.serialize_element(&output[0])?; } } - Json::Array(data) + seq.end() } } } @@ -596,7 +606,7 @@ fn write_shared( // To avoid theme switch latencies as much as possible, we put everything theme related // at the beginning of the html files into another js file. let theme_js = format!( -r#"var themes = document.getElementById("theme-choices"); + r#"var themes = document.getElementById("theme-choices"); var themePicker = document.getElementById("theme-picker"); function showThemeButtonState() {{ @@ -642,8 +652,8 @@ themePicker.onblur = handleThemeButtonsBlur; }}; but.onblur = handleThemeButtonsBlur; themes.appendChild(but); -}});"#, - as_json(&themes)); +}});"#, serde_json::to_string(&themes).unwrap()); + write_minify(&cx.shared.fs, cx.path("theme.js"), &theme_js, options.enable_minification)?; @@ -932,32 +942,48 @@ themePicker.onblur = handleThemeButtonsBlur; } }; - let mut have_impls = false; - let mut implementors = format!(r#"implementors["{}"] = ["#, krate.name); - for imp in imps { - // If the trait and implementation are in the same crate, then - // there's no need to emit information about it (there's inlining - // going on). If they're in different crates then the crate defining - // the trait will be interested in our implementation. - if imp.impl_item.def_id.krate == did.krate { continue } - // If the implementation is from another crate then that crate - // should add it. - if !imp.impl_item.def_id.is_local() { continue } - have_impls = true; - write!(implementors, "{{text:{},synthetic:{},types:{}}},", - as_json(&imp.inner_impl().print().to_string()), - imp.inner_impl().synthetic, - as_json(&collect_paths_for_type(imp.inner_impl().for_.clone()))).unwrap(); + #[derive(Serialize)] + struct Implementor { + text: String, + synthetic: bool, + types: Vec, } - implementors.push_str("];"); + + let implementors = imps + .iter() + .filter_map(|imp| { + // If the trait and implementation are in the same crate, then + // there's no need to emit information about it (there's inlining + // going on). If they're in different crates then the crate defining + // the trait will be interested in our implementation. + // + // If the implementation is from another crate then that crate + // should add it. + if imp.impl_item.def_id.krate == did.krate || !imp.impl_item.def_id.is_local() { + None + } else { + Some(Implementor { + text: imp.inner_impl().print().to_string(), + synthetic: imp.inner_impl().synthetic, + types: collect_paths_for_type(imp.inner_impl().for_.clone()), + }) + } + }) + .collect::>(); // Only create a js file if we have impls to add to it. If the trait is // documented locally though we always create the file to avoid dead // links. - if !have_impls && !cx.cache.paths.contains_key(&did) { + if implementors.is_empty() && !cx.cache.paths.contains_key(&did) { continue; } + let implementors = format!( + r#"implementors["{}"] = {};"#, + krate.name, + serde_json::to_string(&implementors).unwrap() + ); + let mut mydst = dst.clone(); for part in &remote_path[..remote_path.len() - 1] { mydst.push(part); @@ -1456,7 +1482,7 @@ impl Context { if !self.render_redirect_pages { let items = self.build_sidebar_items(&m); let js_dst = self.dst.join("sidebar-items.js"); - let v = format!("initSidebarItems({});", as_json(&items)); + let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap()); scx.fs.write(&js_dst, &v)?; } @@ -2558,8 +2584,11 @@ fn item_trait( write_loading_content(w, ""); } } - write!(w, r#""#, - as_json(&synthetic_types)); + write!( + w, + r#""#, + serde_json::to_string(&synthetic_types).unwrap(), + ); write!(w, r#"