Skip to content

Commit

Permalink
Rollup merge of rust-lang#37190 - QuietMisdreavus:rustdoc-where-newli…
Browse files Browse the repository at this point in the history
…ne, r=GuillaumeGomez

rustdoc: add line breaks to where clauses a la rustfmt

Much like my last PR for rustdoc (rust-lang#36679), this adds line breaks to certain statements based on their line length. Here the focus was on where clauses.

Some examples:
- [Where clause in a trait function](https://shiva.icesoldier.me/custom-std/std/iter/trait.Iterator.html?search=#method.unzip) (also in the trait header block at the top of the page)
- [Where clause on a bare function](https://shiva.icesoldier.me/doc-custom2/petgraph/visit/fn.depth_first_search.html)
- [Where clauses in trait impls on a struct](https://shiva.icesoldier.me/custom-std/std/collections/struct.HashMap.html) (scroll to the bottom) These are regularly not on their own line, but will be given their own line now if their "prefix text" doesn't give them enough room to sensibly print their constraints. HashMap's trait impls provide some examples of both behaviors.

The libstd links above are the whole docs rendered with this, and the "bare function" link above is in another set that pulls some notable crates together. `petgraph` was the one that brought this request up, and that collection also includes [itertools](https://shiva.icesoldier.me/doc-custom2/itertools/trait.Itertools.html) which provided an easy sample to test with.

r? @GuillaumeGomez
  • Loading branch information
eddyb committed Nov 12, 2016
2 parents b33873f + 61cc870 commit 2db360e
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 52 deletions.
84 changes: 61 additions & 23 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ pub struct UnsafetySpace(pub hir::Unsafety);
#[derive(Copy, Clone)]
pub struct ConstnessSpace(pub hir::Constness);
/// Wrapper struct for properly emitting a method declaration.
pub struct Method<'a>(pub &'a clean::FnDecl, pub &'a str);
pub struct Method<'a>(pub &'a clean::FnDecl, pub usize);
/// Similar to VisSpace, but used for mutability
#[derive(Copy, Clone)]
pub struct MutableSpace(pub clean::Mutability);
/// Similar to VisSpace, but used for mutability
#[derive(Copy, Clone)]
pub struct RawMutableSpace(pub clean::Mutability);
/// Wrapper struct for emitting a where clause from Generics.
pub struct WhereClause<'a>(pub &'a clean::Generics);
pub struct WhereClause<'a>(pub &'a clean::Generics, pub usize);
/// Wrapper struct for emitting type parameter bounds.
pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
/// Wrapper struct for emitting a comma-separated list of items
Expand Down Expand Up @@ -157,52 +157,71 @@ impl fmt::Display for clean::Generics {

impl<'a> fmt::Display for WhereClause<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let &WhereClause(gens) = self;
let &WhereClause(gens, pad) = self;
if gens.where_predicates.is_empty() {
return Ok(());
}
let mut clause = String::new();
if f.alternate() {
f.write_str(" ")?;
clause.push_str(" where ");
} else {
f.write_str(" <span class='where'>where ")?;
clause.push_str(" <span class='where'>where ");
}
for (i, pred) in gens.where_predicates.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
if f.alternate() {
clause.push_str(", ");
} else {
clause.push_str(",<br>");
}
}
match pred {
&clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
let bounds = bounds;
if f.alternate() {
write!(f, "{:#}: {:#}", ty, TyParamBounds(bounds))?;
clause.push_str(&format!("{:#}: {:#}", ty, TyParamBounds(bounds)));
} else {
write!(f, "{}: {}", ty, TyParamBounds(bounds))?;
clause.push_str(&format!("{}: {}", ty, TyParamBounds(bounds)));
}
}
&clean::WherePredicate::RegionPredicate { ref lifetime,
ref bounds } => {
write!(f, "{}: ", lifetime)?;
clause.push_str(&format!("{}: ", lifetime));
for (i, lifetime) in bounds.iter().enumerate() {
if i > 0 {
f.write_str(" + ")?;
clause.push_str(" + ");
}

write!(f, "{}", lifetime)?;
clause.push_str(&format!("{}", lifetime));
}
}
&clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
if f.alternate() {
write!(f, "{:#} == {:#}", lhs, rhs)?;
clause.push_str(&format!("{:#} == {:#}", lhs, rhs));
} else {
write!(f, "{} == {}", lhs, rhs)?;
clause.push_str(&format!("{} == {}", lhs, rhs));
}
}
}
}
if !f.alternate() {
f.write_str("</span>")?;
clause.push_str("</span>");
let plain = format!("{:#}", self);
if plain.len() > 80 {
//break it onto its own line regardless, but make sure method impls and trait
//blocks keep their fixed padding (2 and 9, respectively)
let padding = if pad > 10 {
clause = clause.replace("class='where'", "class='where fmt-newline'");
repeat("&nbsp;").take(8).collect::<String>()
} else {
repeat("&nbsp;").take(pad + 6).collect::<String>()
};
clause = clause.replace("<br>", &format!("<br>{}", padding));
} else {
clause = clause.replace("<br>", " ");
}
}
Ok(())
write!(f, "{}", clause)
}
}

Expand Down Expand Up @@ -718,30 +737,43 @@ impl fmt::Display for clean::Type {
}

fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result {
let mut plain = String::new();

if f.alternate() {
write!(f, "impl{:#} ", i.generics)?;
} else {
write!(f, "impl{} ", i.generics)?;
}
plain.push_str(&format!("impl{:#} ", i.generics));

if let Some(ref ty) = i.trait_ {
write!(f, "{}",
if i.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" })?;
if i.polarity == Some(clean::ImplPolarity::Negative) {
write!(f, "!")?;
plain.push_str("!");
}

if link_trait {
fmt::Display::fmt(ty, f)?;
plain.push_str(&format!("{:#}", ty));
} else {
match *ty {
clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => {
let last = path.segments.last().unwrap();
fmt::Display::fmt(&last.name, f)?;
fmt::Display::fmt(&last.params, f)?;
plain.push_str(&format!("{:#}{:#}", last.name, last.params));
}
_ => unreachable!(),
}
}
write!(f, " for ")?;
plain.push_str(" for ");
}

fmt::Display::fmt(&i.for_, f)?;
fmt::Display::fmt(&WhereClause(&i.generics), f)?;
plain.push_str(&format!("{:#}", i.for_));

fmt::Display::fmt(&WhereClause(&i.generics, plain.len() + 1), f)?;
Ok(())
}

Expand Down Expand Up @@ -870,24 +902,30 @@ impl<'a> fmt::Display for Method<'a> {

let mut output: String;
let plain: String;
let pad = repeat(" ").take(indent).collect::<String>();
if arrow.is_empty() {
output = format!("({})", args);
plain = format!("{}({})", indent.replace("&nbsp;", " "), args_plain);
plain = format!("{}({})", pad, args_plain);
} else {
output = format!("({args})<br>{arrow}", args = args, arrow = arrow);
plain = format!("{indent}({args}){arrow}",
indent = indent.replace("&nbsp;", " "),
plain = format!("{pad}({args}){arrow}",
pad = pad,
args = args_plain,
arrow = arrow_plain);
}

if plain.len() > 80 {
let pad = format!("<br>{}", indent);
let pad = repeat("&nbsp;").take(indent).collect::<String>();
let pad = format!("<br>{}", pad);
output = output.replace("<br>", &pad);
} else {
output = output.replace("<br>", "");
}
write!(f, "{}", output)
if f.alternate() {
write!(f, "{}", output.replace("<br>", "\n"))
} else {
write!(f, "{}", output)
}
}
}

Expand Down
Loading

0 comments on commit 2db360e

Please sign in to comment.