Rollup merge of #37190 - QuietMisdreavus:rustdoc-where-newline, r=GuillaumeGomez
rustdoc: add line breaks to where clauses a la rustfmt Much like my last PR for rustdoc (#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
This commit is contained in:
commit
2db360eec1
4 changed files with 156 additions and 52 deletions
|
@ -42,7 +42,7 @@ 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);
|
||||
|
@ -50,7 +50,7 @@ pub struct MutableSpace(pub clean::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
|
||||
|
@ -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(" ").take(8).collect::<String>()
|
||||
} else {
|
||||
repeat(" ").take(pad + 6).collect::<String>()
|
||||
};
|
||||
clause = clause.replace("<br>", &format!("<br>{}", padding));
|
||||
} else {
|
||||
clause = clause.replace("<br>", " ");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
write!(f, "{}", clause)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -870,26 +902,32 @@ 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(" ", " "), 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(" ", " "),
|
||||
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(" ").take(indent).collect::<String>();
|
||||
let pad = format!("<br>{}", pad);
|
||||
output = output.replace("<br>", &pad);
|
||||
} else {
|
||||
output = output.replace("<br>", "");
|
||||
}
|
||||
if f.alternate() {
|
||||
write!(f, "{}", output.replace("<br>", "\n"))
|
||||
} else {
|
||||
write!(f, "{}", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for VisSpace<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
|
|
@ -1972,14 +1972,13 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
UnstableFeatures::Allow => f.constness,
|
||||
_ => hir::Constness::NotConst
|
||||
};
|
||||
let prefix = format!("{}{}{}{:#}fn {}{:#}",
|
||||
let indent = format!("{}{}{}{:#}fn {}{:#}",
|
||||
VisSpace(&it.visibility),
|
||||
ConstnessSpace(vis_constness),
|
||||
UnsafetySpace(f.unsafety),
|
||||
AbiSpace(f.abi),
|
||||
it.name.as_ref().unwrap(),
|
||||
f.generics);
|
||||
let indent = repeat(" ").take(prefix.len()).collect::<String>();
|
||||
f.generics).len();
|
||||
write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
|
||||
{name}{generics}{decl}{where_clause}</pre>",
|
||||
vis = VisSpace(&it.visibility),
|
||||
|
@ -1988,22 +1987,29 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
abi = AbiSpace(f.abi),
|
||||
name = it.name.as_ref().unwrap(),
|
||||
generics = f.generics,
|
||||
where_clause = WhereClause(&f.generics),
|
||||
decl = Method(&f.decl, &indent))?;
|
||||
where_clause = WhereClause(&f.generics, 2),
|
||||
decl = Method(&f.decl, indent))?;
|
||||
document(w, cx, it)
|
||||
}
|
||||
|
||||
fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
t: &clean::Trait) -> fmt::Result {
|
||||
let mut bounds = String::new();
|
||||
let mut bounds_plain = String::new();
|
||||
if !t.bounds.is_empty() {
|
||||
if !bounds.is_empty() {
|
||||
bounds.push(' ');
|
||||
bounds_plain.push(' ');
|
||||
}
|
||||
bounds.push_str(": ");
|
||||
bounds_plain.push_str(": ");
|
||||
for (i, p) in t.bounds.iter().enumerate() {
|
||||
if i > 0 { bounds.push_str(" + "); }
|
||||
if i > 0 {
|
||||
bounds.push_str(" + ");
|
||||
bounds_plain.push_str(" + ");
|
||||
}
|
||||
bounds.push_str(&format!("{}", *p));
|
||||
bounds_plain.push_str(&format!("{:#}", *p));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2014,7 +2020,8 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
it.name.as_ref().unwrap(),
|
||||
t.generics,
|
||||
bounds,
|
||||
WhereClause(&t.generics))?;
|
||||
// Where clauses in traits are indented nine spaces, per rustdoc.css
|
||||
WhereClause(&t.generics, 9))?;
|
||||
|
||||
let types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
|
||||
let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
|
||||
|
@ -2028,7 +2035,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
write!(w, "{{\n")?;
|
||||
for t in &types {
|
||||
write!(w, " ")?;
|
||||
render_assoc_item(w, t, AssocItemLink::Anchor(None))?;
|
||||
render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
|
||||
write!(w, ";\n")?;
|
||||
}
|
||||
if !types.is_empty() && !consts.is_empty() {
|
||||
|
@ -2036,7 +2043,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
}
|
||||
for t in &consts {
|
||||
write!(w, " ")?;
|
||||
render_assoc_item(w, t, AssocItemLink::Anchor(None))?;
|
||||
render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
|
||||
write!(w, ";\n")?;
|
||||
}
|
||||
if !consts.is_empty() && !required.is_empty() {
|
||||
|
@ -2044,7 +2051,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
}
|
||||
for m in &required {
|
||||
write!(w, " ")?;
|
||||
render_assoc_item(w, m, AssocItemLink::Anchor(None))?;
|
||||
render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
|
||||
write!(w, ";\n")?;
|
||||
}
|
||||
if !required.is_empty() && !provided.is_empty() {
|
||||
|
@ -2052,7 +2059,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
}
|
||||
for m in &provided {
|
||||
write!(w, " ")?;
|
||||
render_assoc_item(w, m, AssocItemLink::Anchor(None))?;
|
||||
render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
|
||||
write!(w, " {{ ... }}\n")?;
|
||||
}
|
||||
write!(w, "}}")?;
|
||||
|
@ -2073,7 +2080,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
id = id,
|
||||
stab = m.stability_class(),
|
||||
ns_id = ns_id)?;
|
||||
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)))?;
|
||||
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?;
|
||||
write!(w, "</code>")?;
|
||||
render_stability_since(w, m, t)?;
|
||||
write!(w, "</span></h3>")?;
|
||||
|
@ -2227,7 +2234,8 @@ fn render_stability_since(w: &mut fmt::Formatter,
|
|||
|
||||
fn render_assoc_item(w: &mut fmt::Formatter,
|
||||
item: &clean::Item,
|
||||
link: AssocItemLink) -> fmt::Result {
|
||||
link: AssocItemLink,
|
||||
parent: ItemType) -> fmt::Result {
|
||||
fn method(w: &mut fmt::Formatter,
|
||||
meth: &clean::Item,
|
||||
unsafety: hir::Unsafety,
|
||||
|
@ -2235,7 +2243,8 @@ fn render_assoc_item(w: &mut fmt::Formatter,
|
|||
abi: abi::Abi,
|
||||
g: &clean::Generics,
|
||||
d: &clean::FnDecl,
|
||||
link: AssocItemLink)
|
||||
link: AssocItemLink,
|
||||
parent: ItemType)
|
||||
-> fmt::Result {
|
||||
let name = meth.name.as_ref().unwrap();
|
||||
let anchor = format!("#{}.{}", meth.type_(), name);
|
||||
|
@ -2265,7 +2274,16 @@ fn render_assoc_item(w: &mut fmt::Formatter,
|
|||
AbiSpace(abi),
|
||||
name,
|
||||
*g);
|
||||
let indent = repeat(" ").take(prefix.len()).collect::<String>();
|
||||
let mut indent = prefix.len();
|
||||
let where_indent = if parent == ItemType::Trait {
|
||||
indent += 4;
|
||||
8
|
||||
} else if parent == ItemType::Impl {
|
||||
2
|
||||
} else {
|
||||
let prefix = prefix + &format!("{:#}", Method(d, indent));
|
||||
prefix.lines().last().unwrap().len() + 1
|
||||
};
|
||||
write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
|
||||
{generics}{decl}{where_clause}",
|
||||
ConstnessSpace(vis_constness),
|
||||
|
@ -2274,19 +2292,18 @@ fn render_assoc_item(w: &mut fmt::Formatter,
|
|||
href = href,
|
||||
name = name,
|
||||
generics = *g,
|
||||
decl = Method(d, &indent),
|
||||
where_clause = WhereClause(g))
|
||||
decl = Method(d, indent),
|
||||
where_clause = WhereClause(g, where_indent))
|
||||
}
|
||||
match item.inner {
|
||||
clean::StrippedItem(..) => Ok(()),
|
||||
clean::TyMethodItem(ref m) => {
|
||||
method(w, item, m.unsafety, hir::Constness::NotConst,
|
||||
m.abi, &m.generics, &m.decl, link)
|
||||
m.abi, &m.generics, &m.decl, link, parent)
|
||||
}
|
||||
clean::MethodItem(ref m) => {
|
||||
method(w, item, m.unsafety, m.constness,
|
||||
m.abi, &m.generics, &m.decl,
|
||||
link)
|
||||
m.abi, &m.generics, &m.decl, link, parent)
|
||||
}
|
||||
clean::AssociatedConstItem(ref ty, ref default) => {
|
||||
assoc_const(w, item, ty, default.as_ref(), link)
|
||||
|
@ -2383,11 +2400,15 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||
e: &clean::Enum) -> fmt::Result {
|
||||
write!(w, "<pre class='rust enum'>")?;
|
||||
render_attributes(w, it)?;
|
||||
let padding = format!("{}enum {}{:#} ",
|
||||
VisSpace(&it.visibility),
|
||||
it.name.as_ref().unwrap(),
|
||||
e.generics).len();
|
||||
write!(w, "{}enum {}{}{}",
|
||||
VisSpace(&it.visibility),
|
||||
it.name.as_ref().unwrap(),
|
||||
e.generics,
|
||||
WhereClause(&e.generics))?;
|
||||
WhereClause(&e.generics, padding))?;
|
||||
if e.variants.is_empty() && !e.variants_stripped {
|
||||
write!(w, " {{}}")?;
|
||||
} else {
|
||||
|
@ -2559,17 +2580,23 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
|
|||
fields: &[clean::Item],
|
||||
tab: &str,
|
||||
structhead: bool) -> fmt::Result {
|
||||
let mut plain = String::new();
|
||||
write!(w, "{}{}{}",
|
||||
VisSpace(&it.visibility),
|
||||
if structhead {"struct "} else {""},
|
||||
it.name.as_ref().unwrap())?;
|
||||
plain.push_str(&format!("{}{}{}",
|
||||
VisSpace(&it.visibility),
|
||||
if structhead {"struct "} else {""},
|
||||
it.name.as_ref().unwrap()));
|
||||
if let Some(g) = g {
|
||||
plain.push_str(&format!("{:#}", g));
|
||||
write!(w, "{}", g)?
|
||||
}
|
||||
match ty {
|
||||
doctree::Plain => {
|
||||
if let Some(g) = g {
|
||||
write!(w, "{}", WhereClause(g))?
|
||||
write!(w, "{}", WhereClause(g, plain.len() + 1))?
|
||||
}
|
||||
let mut has_visible_fields = false;
|
||||
write!(w, " {{")?;
|
||||
|
@ -2598,30 +2625,35 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
|
|||
}
|
||||
doctree::Tuple => {
|
||||
write!(w, "(")?;
|
||||
plain.push_str("(");
|
||||
for (i, field) in fields.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(w, ", ")?;
|
||||
plain.push_str(", ");
|
||||
}
|
||||
match field.inner {
|
||||
clean::StrippedItem(box clean::StructFieldItem(..)) => {
|
||||
plain.push_str("_");
|
||||
write!(w, "_")?
|
||||
}
|
||||
clean::StructFieldItem(ref ty) => {
|
||||
plain.push_str(&format!("{}{:#}", VisSpace(&field.visibility), *ty));
|
||||
write!(w, "{}{}", VisSpace(&field.visibility), *ty)?
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
write!(w, ")")?;
|
||||
plain.push_str(")");
|
||||
if let Some(g) = g {
|
||||
write!(w, "{}", WhereClause(g))?
|
||||
write!(w, "{}", WhereClause(g, plain.len() + 1))?
|
||||
}
|
||||
write!(w, ";")?;
|
||||
}
|
||||
doctree::Unit => {
|
||||
// Needed for PhantomData.
|
||||
if let Some(g) = g {
|
||||
write!(w, "{}", WhereClause(g))?
|
||||
write!(w, "{}", WhereClause(g, plain.len() + 1))?
|
||||
}
|
||||
write!(w, ";")?;
|
||||
}
|
||||
|
@ -2634,13 +2666,19 @@ fn render_union(w: &mut fmt::Formatter, it: &clean::Item,
|
|||
fields: &[clean::Item],
|
||||
tab: &str,
|
||||
structhead: bool) -> fmt::Result {
|
||||
let mut plain = String::new();
|
||||
write!(w, "{}{}{}",
|
||||
VisSpace(&it.visibility),
|
||||
if structhead {"union "} else {""},
|
||||
it.name.as_ref().unwrap())?;
|
||||
plain.push_str(&format!("{}{}{}",
|
||||
VisSpace(&it.visibility),
|
||||
if structhead {"union "} else {""},
|
||||
it.name.as_ref().unwrap()));
|
||||
if let Some(g) = g {
|
||||
write!(w, "{}", g)?;
|
||||
write!(w, "{}", WhereClause(g))?;
|
||||
plain.push_str(&format!("{:#}", g));
|
||||
write!(w, "{}", WhereClause(g, plain.len() + 1))?;
|
||||
}
|
||||
|
||||
write!(w, " {{\n{}", tab)?;
|
||||
|
@ -2831,7 +2869,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
|||
write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
|
||||
write!(w, "<span id='{}' class='invisible'>", ns_id)?;
|
||||
write!(w, "<code>")?;
|
||||
render_assoc_item(w, item, link.anchor(&id))?;
|
||||
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?;
|
||||
write!(w, "</code>")?;
|
||||
render_stability_since_raw(w, item.stable_since(), outer_version)?;
|
||||
write!(w, "</span></h4>\n")?;
|
||||
|
@ -2941,10 +2979,11 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
|||
|
||||
fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
t: &clean::Typedef) -> fmt::Result {
|
||||
let indent = format!("type {}{:#} ", it.name.as_ref().unwrap(), t.generics).len();
|
||||
write!(w, "<pre class='rust typedef'>type {}{}{where_clause} = {type_};</pre>",
|
||||
it.name.as_ref().unwrap(),
|
||||
t.generics,
|
||||
where_clause = WhereClause(&t.generics),
|
||||
where_clause = WhereClause(&t.generics, indent),
|
||||
type_ = t.type_)?;
|
||||
|
||||
document(w, cx, it)
|
||||
|
|
|
@ -361,9 +361,17 @@ h4 > code, h3 > code, .invisible > code {
|
|||
position: relative;
|
||||
}
|
||||
/* Shift "where ..." part of method or fn definition down a line */
|
||||
.content .method .where, .content .fn .where { display: block; }
|
||||
.content .method .where,
|
||||
.content .fn .where,
|
||||
.content .where.fmt-newline {
|
||||
display: block;
|
||||
}
|
||||
/* Bit of whitespace to indent it */
|
||||
.content .method .where::before, .content .fn .where::before { content: ' '; }
|
||||
.content .method .where::before,
|
||||
.content .fn .where::before,
|
||||
.content .where.fmt-newline::before {
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
.content .methods > div { margin-left: 40px; }
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
use std::ops::Add;
|
||||
use std::fmt::Display;
|
||||
|
||||
//@count foo/fn.function_with_a_really_long_name.html //pre/br 2
|
||||
pub fn function_with_a_really_long_name(parameter_one: i32,
|
||||
parameter_two: i32)
|
||||
|
@ -19,3 +22,19 @@ pub fn function_with_a_really_long_name(parameter_one: i32,
|
|||
|
||||
//@count foo/fn.short_name.html //pre/br 0
|
||||
pub fn short_name(param: i32) -> i32 { param + 1 }
|
||||
|
||||
//@count foo/fn.where_clause.html //pre/br 4
|
||||
pub fn where_clause<T, U>(param_one: T,
|
||||
param_two: U)
|
||||
where T: Add<U> + Display + Copy,
|
||||
U: Add<T> + Display + Copy,
|
||||
T::Output: Display + Add<U::Output> + Copy,
|
||||
<T::Output as Add<U::Output>>::Output: Display,
|
||||
U::Output: Display + Copy
|
||||
{
|
||||
let x = param_one + param_two;
|
||||
println!("{} + {} = {}", param_one, param_two, x);
|
||||
let y = param_two + param_one;
|
||||
println!("{} + {} = {}", param_two, param_one, y);
|
||||
println!("{} + {} = {}", x, y, x + y);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue