Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace serialize with serde in rustdoc #62359

Merged
merged 1 commit into from
Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3924,6 +3924,8 @@ dependencies = [
"minifier",
"pulldown-cmark 0.5.3",
"rustc-rayon",
"serde",
"serde_json",
"tempfile",
]

Expand Down
2 changes: 2 additions & 0 deletions src/librustdoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
12 changes: 12 additions & 0 deletions src/librustdoc/html/item_type.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -45,6 +49,14 @@ pub enum ItemType {
TraitAlias = 25,
}

impl Serialize for ItemType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
(*self as u8).serialize(serializer)
}
}

impl<'a> From<&'a clean::Item> for ItemType {
fn from(item: &'a clean::Item) -> ItemType {
Expand Down
143 changes: 86 additions & 57 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand All @@ -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;
Expand Down Expand Up @@ -303,19 +305,22 @@ struct IndexItem {
search_type: Option<IndexItemFunctionType>,
}

impl ToJson for IndexItem {
fn to_json(&self) -> Json {
impl Serialize for IndexItem {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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,
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a tuple the right construct for this? Do serialize_tuple and serialize_seq come out the same when run through serde_json?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They will be serialized the same way. This way, it saves the intermediate step of serializing everything to Value to make a Vec<Value>.

.serialize(serializer)
}
}

Expand All @@ -326,18 +331,20 @@ struct Type {
generics: Option<Vec<String>>,
}

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<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(generics) = &self.generics {
seq.serialize_element(&generics)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, could this serialize either (name,) or (name, generics) depending on whether the latter is present? Although this might look a bit silly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, also, doesn't serde have ways of configuring how enum variants are serialized, so that you can just use #[derive(Serialize)] everywhere?

}
None => Json::Null,
seq.end()
} else {
serializer.serialize_none()
}
}
}
Expand All @@ -349,26 +356,29 @@ struct IndexItemFunctionType {
output: Option<Vec<Type>>,
}

impl ToJson for IndexItemFunctionType {
fn to_json(&self) -> Json {
impl Serialize for IndexItemFunctionType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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()
}
}
}
Expand Down Expand Up @@ -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() {{
Expand Down Expand Up @@ -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)?;
Expand Down Expand Up @@ -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<String>,
}
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::<Vec<_>>();

// 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);
Expand Down Expand Up @@ -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)?;
}

Expand Down Expand Up @@ -2558,8 +2584,11 @@ fn item_trait(
write_loading_content(w, "</div>");
}
}
write!(w, r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
as_json(&synthetic_types));
write!(
w,
r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
serde_json::to_string(&synthetic_types).unwrap(),
);

write!(w, r#"<script type="text/javascript" async
src="{root_path}/implementors/{path}/{ty}.{name}.js">
Expand Down
34 changes: 23 additions & 11 deletions src/librustdoc/html/render/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use std::path::{Path, PathBuf};
use std::collections::BTreeMap;
use syntax::source_map::FileName;
use syntax::symbol::sym;
use serialize::json::{ToJson, Json, as_json};

use serde::Serialize;

use super::{ItemType, IndexItem, IndexItemFunctionType, Impl, shorten, plain_summary_line};
use super::{Type, RenderInfo};
Expand Down Expand Up @@ -544,7 +545,7 @@ fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Pat
fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
let mut nodeid_to_pathid = FxHashMap::default();
let mut crate_items = Vec::with_capacity(cache.search_index.len());
let mut crate_paths = Vec::<Json>::new();
let mut crate_paths = vec![];

let Cache { ref mut search_index,
ref orphan_impl_items,
Expand Down Expand Up @@ -581,7 +582,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
lastpathid += 1;

let &(ref fqp, short) = paths.get(&nodeid).unwrap();
crate_paths.push(((short as usize), fqp.last().unwrap().clone()).to_json());
crate_paths.push((short, fqp.last().unwrap().clone()));
pathid
}
});
Expand All @@ -592,22 +593,33 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
} else {
lastpath = item.path.clone();
}
crate_items.push(item.to_json());
crate_items.push(&*item);
}

let crate_doc = krate.module.as_ref().map(|module| {
shorten(plain_summary_line(module.doc_value()))
}).unwrap_or(String::new());

let mut crate_data = BTreeMap::new();
crate_data.insert("doc".to_owned(), Json::String(crate_doc));
crate_data.insert("i".to_owned(), Json::Array(crate_items));
crate_data.insert("p".to_owned(), Json::Array(crate_paths));
#[derive(Serialize)]
struct CrateData<'a> {
doc: String,
#[serde(rename = "i")]
items: Vec<&'a IndexItem>,
#[serde(rename = "p")]
paths: Vec<(ItemType, String)>,
}

// Collect the index into a string
format!("searchIndex[{}] = {};",
as_json(&krate.name),
Json::Object(crate_data))
format!(
r#"searchIndex["{}"] = {};"#,
krate.name,
serde_json::to_string(&CrateData {
doc: crate_doc,
items: crate_items,
paths: crate_paths,
})
.unwrap()
)
}

fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ extern crate rustc_parse;
extern crate rustc_target;
extern crate rustc_typeck;
extern crate rustc_lexer;
extern crate serialize;
extern crate syntax;
extern crate syntax_expand;
extern crate syntax_pos;
Expand Down