Skip to content

Commit 2db360e

Browse files
authored
Rollup merge of rust-lang#37190 - QuietMisdreavus:rustdoc-where-newline, 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
2 parents b33873f + 61cc870 commit 2db360e

File tree

4 files changed

+156
-52
lines changed

4 files changed

+156
-52
lines changed

src/librustdoc/html/format.rs

+61-23
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ pub struct UnsafetySpace(pub hir::Unsafety);
4242
#[derive(Copy, Clone)]
4343
pub struct ConstnessSpace(pub hir::Constness);
4444
/// Wrapper struct for properly emitting a method declaration.
45-
pub struct Method<'a>(pub &'a clean::FnDecl, pub &'a str);
45+
pub struct Method<'a>(pub &'a clean::FnDecl, pub usize);
4646
/// Similar to VisSpace, but used for mutability
4747
#[derive(Copy, Clone)]
4848
pub struct MutableSpace(pub clean::Mutability);
4949
/// Similar to VisSpace, but used for mutability
5050
#[derive(Copy, Clone)]
5151
pub struct RawMutableSpace(pub clean::Mutability);
5252
/// Wrapper struct for emitting a where clause from Generics.
53-
pub struct WhereClause<'a>(pub &'a clean::Generics);
53+
pub struct WhereClause<'a>(pub &'a clean::Generics, pub usize);
5454
/// Wrapper struct for emitting type parameter bounds.
5555
pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
5656
/// Wrapper struct for emitting a comma-separated list of items
@@ -157,52 +157,71 @@ impl fmt::Display for clean::Generics {
157157

158158
impl<'a> fmt::Display for WhereClause<'a> {
159159
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160-
let &WhereClause(gens) = self;
160+
let &WhereClause(gens, pad) = self;
161161
if gens.where_predicates.is_empty() {
162162
return Ok(());
163163
}
164+
let mut clause = String::new();
164165
if f.alternate() {
165-
f.write_str(" ")?;
166+
clause.push_str(" where ");
166167
} else {
167-
f.write_str(" <span class='where'>where ")?;
168+
clause.push_str(" <span class='where'>where ");
168169
}
169170
for (i, pred) in gens.where_predicates.iter().enumerate() {
170171
if i > 0 {
171-
f.write_str(", ")?;
172+
if f.alternate() {
173+
clause.push_str(", ");
174+
} else {
175+
clause.push_str(",<br>");
176+
}
172177
}
173178
match pred {
174179
&clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
175180
let bounds = bounds;
176181
if f.alternate() {
177-
write!(f, "{:#}: {:#}", ty, TyParamBounds(bounds))?;
182+
clause.push_str(&format!("{:#}: {:#}", ty, TyParamBounds(bounds)));
178183
} else {
179-
write!(f, "{}: {}", ty, TyParamBounds(bounds))?;
184+
clause.push_str(&format!("{}: {}", ty, TyParamBounds(bounds)));
180185
}
181186
}
182187
&clean::WherePredicate::RegionPredicate { ref lifetime,
183188
ref bounds } => {
184-
write!(f, "{}: ", lifetime)?;
189+
clause.push_str(&format!("{}: ", lifetime));
185190
for (i, lifetime) in bounds.iter().enumerate() {
186191
if i > 0 {
187-
f.write_str(" + ")?;
192+
clause.push_str(" + ");
188193
}
189194

190-
write!(f, "{}", lifetime)?;
195+
clause.push_str(&format!("{}", lifetime));
191196
}
192197
}
193198
&clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
194199
if f.alternate() {
195-
write!(f, "{:#} == {:#}", lhs, rhs)?;
200+
clause.push_str(&format!("{:#} == {:#}", lhs, rhs));
196201
} else {
197-
write!(f, "{} == {}", lhs, rhs)?;
202+
clause.push_str(&format!("{} == {}", lhs, rhs));
198203
}
199204
}
200205
}
201206
}
202207
if !f.alternate() {
203-
f.write_str("</span>")?;
208+
clause.push_str("</span>");
209+
let plain = format!("{:#}", self);
210+
if plain.len() > 80 {
211+
//break it onto its own line regardless, but make sure method impls and trait
212+
//blocks keep their fixed padding (2 and 9, respectively)
213+
let padding = if pad > 10 {
214+
clause = clause.replace("class='where'", "class='where fmt-newline'");
215+
repeat("&nbsp;").take(8).collect::<String>()
216+
} else {
217+
repeat("&nbsp;").take(pad + 6).collect::<String>()
218+
};
219+
clause = clause.replace("<br>", &format!("<br>{}", padding));
220+
} else {
221+
clause = clause.replace("<br>", " ");
222+
}
204223
}
205-
Ok(())
224+
write!(f, "{}", clause)
206225
}
207226
}
208227

@@ -718,30 +737,43 @@ impl fmt::Display for clean::Type {
718737
}
719738

720739
fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result {
740+
let mut plain = String::new();
741+
721742
if f.alternate() {
722743
write!(f, "impl{:#} ", i.generics)?;
723744
} else {
724745
write!(f, "impl{} ", i.generics)?;
725746
}
747+
plain.push_str(&format!("impl{:#} ", i.generics));
748+
726749
if let Some(ref ty) = i.trait_ {
727-
write!(f, "{}",
728-
if i.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" })?;
750+
if i.polarity == Some(clean::ImplPolarity::Negative) {
751+
write!(f, "!")?;
752+
plain.push_str("!");
753+
}
754+
729755
if link_trait {
730756
fmt::Display::fmt(ty, f)?;
757+
plain.push_str(&format!("{:#}", ty));
731758
} else {
732759
match *ty {
733760
clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => {
734761
let last = path.segments.last().unwrap();
735762
fmt::Display::fmt(&last.name, f)?;
736763
fmt::Display::fmt(&last.params, f)?;
764+
plain.push_str(&format!("{:#}{:#}", last.name, last.params));
737765
}
738766
_ => unreachable!(),
739767
}
740768
}
741769
write!(f, " for ")?;
770+
plain.push_str(" for ");
742771
}
772+
743773
fmt::Display::fmt(&i.for_, f)?;
744-
fmt::Display::fmt(&WhereClause(&i.generics), f)?;
774+
plain.push_str(&format!("{:#}", i.for_));
775+
776+
fmt::Display::fmt(&WhereClause(&i.generics, plain.len() + 1), f)?;
745777
Ok(())
746778
}
747779

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

871903
let mut output: String;
872904
let plain: String;
905+
let pad = repeat(" ").take(indent).collect::<String>();
873906
if arrow.is_empty() {
874907
output = format!("({})", args);
875-
plain = format!("{}({})", indent.replace("&nbsp;", " "), args_plain);
908+
plain = format!("{}({})", pad, args_plain);
876909
} else {
877910
output = format!("({args})<br>{arrow}", args = args, arrow = arrow);
878-
plain = format!("{indent}({args}){arrow}",
879-
indent = indent.replace("&nbsp;", " "),
911+
plain = format!("{pad}({args}){arrow}",
912+
pad = pad,
880913
args = args_plain,
881914
arrow = arrow_plain);
882915
}
883916

884917
if plain.len() > 80 {
885-
let pad = format!("<br>{}", indent);
918+
let pad = repeat("&nbsp;").take(indent).collect::<String>();
919+
let pad = format!("<br>{}", pad);
886920
output = output.replace("<br>", &pad);
887921
} else {
888922
output = output.replace("<br>", "");
889923
}
890-
write!(f, "{}", output)
924+
if f.alternate() {
925+
write!(f, "{}", output.replace("<br>", "\n"))
926+
} else {
927+
write!(f, "{}", output)
928+
}
891929
}
892930
}
893931

0 commit comments

Comments
 (0)