]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/html/format.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / librustdoc / html / format.rs
CommitLineData
1a4d82fc
JJ
1// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! HTML formatting module
12//!
85aaf69f 13//! This module contains a large number of `fmt::Display` implementations for
1a4d82fc
JJ
14//! various types in `rustdoc::clean`. These implementations all currently
15//! assume that HTML output is desired, although it may be possible to redesign
16//! them in the future to instead emit any format desired.
17
18use std::fmt;
19use std::iter::repeat;
20
92a42be0 21use rustc::middle::cstore::LOCAL_CRATE;
5bcae85e 22use rustc::hir::def_id::DefId;
9346a6ac 23use syntax::abi::Abi;
54a0048b 24use rustc::hir;
1a4d82fc
JJ
25
26use clean;
a7813a04 27use core::DocAccessLevels;
1a4d82fc 28use html::item_type::ItemType;
a7813a04 29use html::escape::Escape;
1a4d82fc
JJ
30use html::render;
31use html::render::{cache, CURRENT_LOCATION_KEY};
32
33/// Helper to render an optional visibility with a space after it (if the
34/// visibility is preset)
c34b1796 35#[derive(Copy, Clone)]
a7813a04 36pub struct VisSpace<'a>(pub &'a Option<clean::Visibility>);
1a4d82fc
JJ
37/// Similarly to VisSpace, this structure is used to render a function style with a
38/// space after it.
c34b1796 39#[derive(Copy, Clone)]
e9174d1e 40pub struct UnsafetySpace(pub hir::Unsafety);
62682a34
SL
41/// Similarly to VisSpace, this structure is used to render a function constness
42/// with a space after it.
43#[derive(Copy, Clone)]
e9174d1e 44pub struct ConstnessSpace(pub hir::Constness);
1a4d82fc 45/// Wrapper struct for properly emitting a method declaration.
a7813a04 46pub struct Method<'a>(pub &'a clean::FnDecl);
1a4d82fc 47/// Similar to VisSpace, but used for mutability
c34b1796 48#[derive(Copy, Clone)]
1a4d82fc
JJ
49pub struct MutableSpace(pub clean::Mutability);
50/// Similar to VisSpace, but used for mutability
c34b1796 51#[derive(Copy, Clone)]
1a4d82fc 52pub struct RawMutableSpace(pub clean::Mutability);
1a4d82fc
JJ
53/// Wrapper struct for emitting a where clause from Generics.
54pub struct WhereClause<'a>(pub &'a clean::Generics);
55/// Wrapper struct for emitting type parameter bounds.
56pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
57/// Wrapper struct for emitting a comma-separated list of items
58pub struct CommaSep<'a, T: 'a>(pub &'a [T]);
9346a6ac 59pub struct AbiSpace(pub Abi);
1a4d82fc 60
a7813a04
XL
61pub struct HRef<'a> {
62 pub did: DefId,
63 pub text: &'a str,
64}
65
54a0048b 66impl<'a> VisSpace<'a> {
a7813a04 67 pub fn get(self) -> &'a Option<clean::Visibility> {
54a0048b 68 let VisSpace(v) = self; v
1a4d82fc
JJ
69 }
70}
71
72impl UnsafetySpace {
e9174d1e 73 pub fn get(&self) -> hir::Unsafety {
1a4d82fc
JJ
74 let UnsafetySpace(v) = *self; v
75 }
76}
77
62682a34 78impl ConstnessSpace {
e9174d1e 79 pub fn get(&self) -> hir::Constness {
62682a34
SL
80 let ConstnessSpace(v) = *self; v
81 }
82}
83
85aaf69f 84impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
1a4d82fc
JJ
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 for (i, item) in self.0.iter().enumerate() {
54a0048b
SL
87 if i != 0 { write!(f, ", ")?; }
88 write!(f, "{}", item)?;
1a4d82fc
JJ
89 }
90 Ok(())
91 }
92}
93
85aaf69f 94impl<'a> fmt::Display for TyParamBounds<'a> {
1a4d82fc
JJ
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 let &TyParamBounds(bounds) = self;
97 for (i, bound) in bounds.iter().enumerate() {
98 if i > 0 {
54a0048b 99 f.write_str(" + ")?;
1a4d82fc 100 }
54a0048b 101 write!(f, "{}", *bound)?;
1a4d82fc
JJ
102 }
103 Ok(())
104 }
105}
106
85aaf69f 107impl fmt::Display for clean::Generics {
1a4d82fc 108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9346a6ac 109 if self.lifetimes.is_empty() && self.type_params.is_empty() { return Ok(()) }
54a0048b 110 f.write_str("&lt;")?;
1a4d82fc
JJ
111
112 for (i, life) in self.lifetimes.iter().enumerate() {
113 if i > 0 {
3157f602 114 f.write_str(",&nbsp;")?;
1a4d82fc 115 }
54a0048b 116 write!(f, "{}", *life)?;
1a4d82fc
JJ
117 }
118
9346a6ac
AL
119 if !self.type_params.is_empty() {
120 if !self.lifetimes.is_empty() {
3157f602 121 f.write_str(",&nbsp;")?;
1a4d82fc
JJ
122 }
123 for (i, tp) in self.type_params.iter().enumerate() {
124 if i > 0 {
3157f602 125 f.write_str(",&nbsp;")?
1a4d82fc 126 }
54a0048b 127 f.write_str(&tp.name)?;
1a4d82fc 128
9346a6ac 129 if !tp.bounds.is_empty() {
3157f602 130 write!(f, ":&nbsp;{}", TyParamBounds(&tp.bounds))?;
1a4d82fc
JJ
131 }
132
3157f602
XL
133 if let Some(ref ty) = tp.default {
134 write!(f, "&nbsp;=&nbsp;{}", ty)?;
1a4d82fc
JJ
135 };
136 }
137 }
54a0048b 138 f.write_str("&gt;")?;
1a4d82fc
JJ
139 Ok(())
140 }
141}
142
85aaf69f 143impl<'a> fmt::Display for WhereClause<'a> {
1a4d82fc
JJ
144 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145 let &WhereClause(gens) = self;
9346a6ac 146 if gens.where_predicates.is_empty() {
1a4d82fc
JJ
147 return Ok(());
148 }
54a0048b 149 f.write_str(" <span class='where'>where ")?;
1a4d82fc
JJ
150 for (i, pred) in gens.where_predicates.iter().enumerate() {
151 if i > 0 {
54a0048b 152 f.write_str(", ")?;
1a4d82fc
JJ
153 }
154 match pred {
155 &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
85aaf69f 156 let bounds = bounds;
54a0048b 157 write!(f, "{}: {}", ty, TyParamBounds(bounds))?;
1a4d82fc
JJ
158 }
159 &clean::WherePredicate::RegionPredicate { ref lifetime,
160 ref bounds } => {
54a0048b 161 write!(f, "{}: ", lifetime)?;
1a4d82fc
JJ
162 for (i, lifetime) in bounds.iter().enumerate() {
163 if i > 0 {
54a0048b 164 f.write_str(" + ")?;
1a4d82fc
JJ
165 }
166
54a0048b 167 write!(f, "{}", lifetime)?;
1a4d82fc
JJ
168 }
169 }
85aaf69f 170 &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
54a0048b 171 write!(f, "{} == {}", lhs, rhs)?;
1a4d82fc
JJ
172 }
173 }
174 }
54a0048b 175 f.write_str("</span>")?;
1a4d82fc
JJ
176 Ok(())
177 }
178}
179
85aaf69f 180impl fmt::Display for clean::Lifetime {
1a4d82fc 181 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54a0048b 182 f.write_str(self.get_ref())?;
1a4d82fc
JJ
183 Ok(())
184 }
185}
186
85aaf69f 187impl fmt::Display for clean::PolyTrait {
1a4d82fc 188 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9346a6ac 189 if !self.lifetimes.is_empty() {
54a0048b 190 f.write_str("for&lt;")?;
1a4d82fc
JJ
191 for (i, lt) in self.lifetimes.iter().enumerate() {
192 if i > 0 {
54a0048b 193 f.write_str(", ")?;
1a4d82fc 194 }
54a0048b 195 write!(f, "{}", lt)?;
1a4d82fc 196 }
54a0048b 197 f.write_str("&gt; ")?;
1a4d82fc
JJ
198 }
199 write!(f, "{}", self.trait_)
200 }
201}
202
85aaf69f 203impl fmt::Display for clean::TyParamBound {
1a4d82fc
JJ
204 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
205 match *self {
206 clean::RegionBound(ref lt) => {
207 write!(f, "{}", *lt)
208 }
209 clean::TraitBound(ref ty, modifier) => {
210 let modifier_str = match modifier {
e9174d1e
SL
211 hir::TraitBoundModifier::None => "",
212 hir::TraitBoundModifier::Maybe => "?",
1a4d82fc
JJ
213 };
214 write!(f, "{}{}", modifier_str, *ty)
215 }
216 }
217 }
218}
219
85aaf69f 220impl fmt::Display for clean::PathParameters {
1a4d82fc
JJ
221 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
222 match *self {
223 clean::PathParameters::AngleBracketed {
224 ref lifetimes, ref types, ref bindings
225 } => {
9346a6ac 226 if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
54a0048b 227 f.write_str("&lt;")?;
1a4d82fc 228 let mut comma = false;
85aaf69f 229 for lifetime in lifetimes {
1a4d82fc 230 if comma {
3157f602 231 f.write_str(",&nbsp;")?;
1a4d82fc
JJ
232 }
233 comma = true;
54a0048b 234 write!(f, "{}", *lifetime)?;
1a4d82fc 235 }
85aaf69f 236 for ty in types {
1a4d82fc 237 if comma {
3157f602 238 f.write_str(",&nbsp;")?;
1a4d82fc
JJ
239 }
240 comma = true;
54a0048b 241 write!(f, "{}", *ty)?;
1a4d82fc 242 }
85aaf69f 243 for binding in bindings {
1a4d82fc 244 if comma {
3157f602 245 f.write_str(",&nbsp;")?;
1a4d82fc
JJ
246 }
247 comma = true;
54a0048b 248 write!(f, "{}", *binding)?;
1a4d82fc 249 }
54a0048b 250 f.write_str("&gt;")?;
1a4d82fc
JJ
251 }
252 }
253 clean::PathParameters::Parenthesized { ref inputs, ref output } => {
54a0048b 254 f.write_str("(")?;
1a4d82fc 255 let mut comma = false;
85aaf69f 256 for ty in inputs {
1a4d82fc 257 if comma {
54a0048b 258 f.write_str(", ")?;
1a4d82fc
JJ
259 }
260 comma = true;
54a0048b 261 write!(f, "{}", *ty)?;
1a4d82fc 262 }
54a0048b 263 f.write_str(")")?;
1a4d82fc 264 if let Some(ref ty) = *output {
54a0048b
SL
265 f.write_str(" -&gt; ")?;
266 write!(f, "{}", ty)?;
1a4d82fc
JJ
267 }
268 }
269 }
270 Ok(())
271 }
272}
273
85aaf69f 274impl fmt::Display for clean::PathSegment {
1a4d82fc 275 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54a0048b 276 f.write_str(&self.name)?;
1a4d82fc
JJ
277 write!(f, "{}", self.params)
278 }
279}
280
85aaf69f 281impl fmt::Display for clean::Path {
1a4d82fc
JJ
282 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
283 if self.global {
54a0048b 284 f.write_str("::")?
1a4d82fc
JJ
285 }
286
287 for (i, seg) in self.segments.iter().enumerate() {
288 if i > 0 {
54a0048b 289 f.write_str("::")?
1a4d82fc 290 }
54a0048b 291 write!(f, "{}", seg)?;
1a4d82fc
JJ
292 }
293 Ok(())
294 }
295}
296
e9174d1e 297pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
9346a6ac 298 let cache = cache();
a7813a04
XL
299 if !did.is_local() && !cache.access_levels.is_doc_reachable(did) {
300 return None
301 }
302
9346a6ac 303 let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone());
5bcae85e
SL
304 let (fqp, shortty, mut url) = match cache.paths.get(&did) {
305 Some(&(ref fqp, shortty)) => {
306 (fqp, shortty, repeat("../").take(loc.len()).collect())
307 }
308 None => match cache.external_paths.get(&did) {
309 Some(&(ref fqp, shortty)) => {
310 (fqp, shortty, match cache.extern_locations[&did.krate] {
311 (_, render::Remote(ref s)) => s.to_string(),
312 (_, render::Local) => repeat("../").take(loc.len()).collect(),
313 (_, render::Unknown) => return None,
314 })
315 }
316 None => return None,
9346a6ac
AL
317 }
318 };
319 for component in &fqp[..fqp.len() - 1] {
320 url.push_str(component);
321 url.push_str("/");
322 }
323 match shortty {
324 ItemType::Module => {
325 url.push_str(fqp.last().unwrap());
326 url.push_str("/index.html");
327 }
328 _ => {
329 url.push_str(shortty.to_static_str());
330 url.push_str(".");
331 url.push_str(fqp.last().unwrap());
332 url.push_str(".html");
333 }
334 }
335 Some((url, shortty, fqp.to_vec()))
336}
337
1a4d82fc
JJ
338/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
339/// rendering function with the necessary arguments for linking to a local path.
e9174d1e 340fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
1a4d82fc 341 print_all: bool) -> fmt::Result {
1a4d82fc 342 let last = path.segments.last().unwrap();
85aaf69f 343 let rel_root = match &*path.segments[0].name {
1a4d82fc
JJ
344 "self" => Some("./".to_string()),
345 _ => None,
346 };
347
348 if print_all {
349 let amt = path.segments.len() - 1;
350 match rel_root {
62682a34 351 Some(mut root) => {
85aaf69f 352 for seg in &path.segments[..amt] {
9346a6ac 353 if "super" == seg.name || "self" == seg.name {
54a0048b 354 write!(w, "{}::", seg.name)?;
1a4d82fc 355 } else {
85aaf69f 356 root.push_str(&seg.name);
1a4d82fc 357 root.push_str("/");
54a0048b
SL
358 write!(w, "<a class='mod'
359 href='{}index.html'>{}</a>::",
360 root,
361 seg.name)?;
1a4d82fc
JJ
362 }
363 }
364 }
365 None => {
85aaf69f 366 for seg in &path.segments[..amt] {
54a0048b 367 write!(w, "{}::", seg.name)?;
1a4d82fc
JJ
368 }
369 }
370 }
371 }
a7813a04 372 write!(w, "{}{}", HRef::new(did, &last.name), last.params)?;
1a4d82fc
JJ
373 Ok(())
374}
375
376fn primitive_link(f: &mut fmt::Formatter,
377 prim: clean::PrimitiveType,
378 name: &str) -> fmt::Result {
379 let m = cache();
380 let mut needs_termination = false;
381 match m.primitive_locations.get(&prim) {
e9174d1e 382 Some(&LOCAL_CRATE) => {
1a4d82fc
JJ
383 let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
384 let len = if len == 0 {0} else {len - 1};
54a0048b
SL
385 write!(f, "<a class='primitive' href='{}primitive.{}.html'>",
386 repeat("../").take(len).collect::<String>(),
387 prim.to_url_str())?;
1a4d82fc
JJ
388 needs_termination = true;
389 }
390 Some(&cnum) => {
c34b1796 391 let loc = match m.extern_locations[&cnum] {
5bcae85e
SL
392 (ref cname, render::Remote(ref s)) => Some((cname, s.to_string())),
393 (ref cname, render::Local) => {
1a4d82fc 394 let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
5bcae85e 395 Some((cname, repeat("../").take(len).collect::<String>()))
1a4d82fc 396 }
d9579d0f 397 (_, render::Unknown) => None,
1a4d82fc 398 };
5bcae85e 399 if let Some((cname, root)) = loc {
3157f602
XL
400 write!(f, "<a class='primitive' href='{}{}/primitive.{}.html'>",
401 root,
5bcae85e 402 cname,
3157f602
XL
403 prim.to_url_str())?;
404 needs_termination = true;
1a4d82fc
JJ
405 }
406 }
407 None => {}
408 }
54a0048b 409 write!(f, "{}", name)?;
1a4d82fc 410 if needs_termination {
54a0048b 411 write!(f, "</a>")?;
1a4d82fc
JJ
412 }
413 Ok(())
414}
415
416/// Helper to render type parameters
417fn tybounds(w: &mut fmt::Formatter,
418 typarams: &Option<Vec<clean::TyParamBound> >) -> fmt::Result {
419 match *typarams {
420 Some(ref params) => {
85aaf69f 421 for param in params {
54a0048b
SL
422 write!(w, " + ")?;
423 write!(w, "{}", *param)?;
1a4d82fc
JJ
424 }
425 Ok(())
426 }
427 None => Ok(())
428 }
429}
430
a7813a04
XL
431impl<'a> HRef<'a> {
432 pub fn new(did: DefId, text: &'a str) -> HRef<'a> {
433 HRef { did: did, text: text }
434 }
435}
436
437impl<'a> fmt::Display for HRef<'a> {
438 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
439 match href(self.did) {
440 Some((url, shortty, fqp)) => {
441 write!(f, "<a class='{}' href='{}' title='{}'>{}</a>",
442 shortty, url, fqp.join("::"), self.text)
443 }
444 _ => write!(f, "{}", self.text),
445 }
446 }
447}
448
85aaf69f 449impl fmt::Display for clean::Type {
1a4d82fc
JJ
450 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
451 match *self {
1a4d82fc 452 clean::Generic(ref name) => {
85aaf69f 453 f.write_str(name)
1a4d82fc 454 }
62682a34
SL
455 clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
456 // Paths like T::Output and Self::Output should be rendered with all segments
54a0048b 457 resolved_path(f, did, path, is_generic)?;
1a4d82fc
JJ
458 tybounds(f, typarams)
459 }
460 clean::Infer => write!(f, "_"),
461 clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()),
1a4d82fc
JJ
462 clean::BareFunction(ref decl) => {
463 write!(f, "{}{}fn{}{}",
464 UnsafetySpace(decl.unsafety),
a7813a04 465 AbiSpace(decl.abi),
1a4d82fc
JJ
466 decl.generics,
467 decl.decl)
468 }
469 clean::Tuple(ref typs) => {
5bcae85e 470 match &typs[..] {
3157f602
XL
471 &[] => primitive_link(f, clean::PrimitiveTuple, "()"),
472 &[ref one] => {
54a0048b
SL
473 primitive_link(f, clean::PrimitiveTuple, "(")?;
474 write!(f, "{},", one)?;
7453a54e
SL
475 primitive_link(f, clean::PrimitiveTuple, ")")
476 }
477 many => {
54a0048b
SL
478 primitive_link(f, clean::PrimitiveTuple, "(")?;
479 write!(f, "{}", CommaSep(&many))?;
7453a54e
SL
480 primitive_link(f, clean::PrimitiveTuple, ")")
481 }
482 }
1a4d82fc
JJ
483 }
484 clean::Vector(ref t) => {
54a0048b
SL
485 primitive_link(f, clean::Slice, &format!("["))?;
486 write!(f, "{}", t)?;
7453a54e 487 primitive_link(f, clean::Slice, &format!("]"))
1a4d82fc
JJ
488 }
489 clean::FixedVector(ref t, ref s) => {
54a0048b
SL
490 primitive_link(f, clean::PrimitiveType::Array, "[")?;
491 write!(f, "{}", t)?;
c34b1796 492 primitive_link(f, clean::PrimitiveType::Array,
a7813a04 493 &format!("; {}]", Escape(s)))
1a4d82fc 494 }
5bcae85e 495 clean::Never => f.write_str("!"),
1a4d82fc 496 clean::RawPointer(m, ref t) => {
7453a54e
SL
497 match **t {
498 clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
499 primitive_link(f, clean::PrimitiveType::PrimitiveRawPointer,
500 &format!("*{}{}", RawMutableSpace(m), t))
501 }
502 _ => {
54a0048b
SL
503 primitive_link(f, clean::PrimitiveType::PrimitiveRawPointer,
504 &format!("*{}", RawMutableSpace(m)))?;
7453a54e
SL
505 write!(f, "{}", t)
506 }
507 }
1a4d82fc
JJ
508 }
509 clean::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty} => {
510 let lt = match *l {
511 Some(ref l) => format!("{} ", *l),
512 _ => "".to_string(),
513 };
514 let m = MutableSpace(mutability);
515 match **ty {
516 clean::Vector(ref bt) => { // BorrowedRef{ ... Vector(T) } is &[T]
517 match **bt {
518 clean::Generic(_) =>
519 primitive_link(f, clean::Slice,
85aaf69f 520 &format!("&amp;{}{}[{}]", lt, m, **bt)),
1a4d82fc 521 _ => {
54a0048b
SL
522 primitive_link(f, clean::Slice, &format!("&amp;{}{}[", lt, m))?;
523 write!(f, "{}", **bt)?;
1a4d82fc
JJ
524 primitive_link(f, clean::Slice, "]")
525 }
526 }
527 }
528 _ => {
529 write!(f, "&amp;{}{}{}", lt, m, **ty)
530 }
531 }
532 }
533 clean::PolyTraitRef(ref bounds) => {
534 for (i, bound) in bounds.iter().enumerate() {
535 if i != 0 {
54a0048b 536 write!(f, " + ")?;
1a4d82fc 537 }
54a0048b 538 write!(f, "{}", *bound)?;
1a4d82fc
JJ
539 }
540 Ok(())
541 }
5bcae85e
SL
542 clean::ImplTrait(ref bounds) => {
543 write!(f, "impl ")?;
544 for (i, bound) in bounds.iter().enumerate() {
545 if i != 0 {
546 write!(f, " + ")?;
547 }
548 write!(f, "{}", *bound)?;
549 }
550 Ok(())
551 }
9346a6ac
AL
552 // It's pretty unsightly to look at `<A as B>::C` in output, and
553 // we've got hyperlinking on our side, so try to avoid longer
554 // notation as much as possible by making `C` a hyperlink to trait
555 // `B` to disambiguate.
556 //
557 // FIXME: this is still a lossy conversion and there should probably
558 // be a better way of representing this in general? Most of
559 // the ugliness comes from inlining across crates where
560 // everything comes in as a fully resolved QPath (hard to
561 // look at).
562 clean::QPath {
563 ref name,
564 ref self_type,
565 trait_: box clean::ResolvedPath { did, ref typarams, .. },
566 } => {
54a0048b 567 write!(f, "{}::", self_type)?;
9346a6ac 568 let path = clean::Path::singleton(name.clone());
54a0048b 569 resolved_path(f, did, &path, false)?;
9346a6ac
AL
570
571 // FIXME: `typarams` are not rendered, and this seems bad?
572 drop(typarams);
573 Ok(())
574 }
1a4d82fc
JJ
575 clean::QPath { ref name, ref self_type, ref trait_ } => {
576 write!(f, "&lt;{} as {}&gt;::{}", self_type, trait_, name)
577 }
578 clean::Unique(..) => {
579 panic!("should have been cleaned")
580 }
581 }
582 }
583}
584
a7813a04
XL
585fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result {
586 write!(f, "impl{} ", i.generics)?;
587 if let Some(ref ty) = i.trait_ {
588 write!(f, "{}",
589 if i.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" })?;
590 if link_trait {
591 write!(f, "{}", *ty)?;
592 } else {
593 match *ty {
594 clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => {
595 let last = path.segments.last().unwrap();
596 write!(f, "{}{}", last.name, last.params)?;
597 }
598 _ => unreachable!(),
599 }
600 }
601 write!(f, " for ")?;
602 }
603 write!(f, "{}{}", i.for_, WhereClause(&i.generics))?;
604 Ok(())
605}
606
c1a9b12d
SL
607impl fmt::Display for clean::Impl {
608 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
a7813a04 609 fmt_impl(self, f, true)
c1a9b12d
SL
610 }
611}
612
a7813a04
XL
613// The difference from above is that trait is not hyperlinked.
614pub fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut fmt::Formatter) -> fmt::Result {
615 fmt_impl(i, f, false)
616}
617
85aaf69f 618impl fmt::Display for clean::Arguments {
1a4d82fc
JJ
619 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
620 for (i, input) in self.values.iter().enumerate() {
54a0048b 621 if i > 0 { write!(f, ", ")?; }
9346a6ac 622 if !input.name.is_empty() {
54a0048b 623 write!(f, "{}: ", input.name)?;
1a4d82fc 624 }
54a0048b 625 write!(f, "{}", input.type_)?;
1a4d82fc
JJ
626 }
627 Ok(())
628 }
629}
630
85aaf69f 631impl fmt::Display for clean::FunctionRetTy {
1a4d82fc
JJ
632 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
633 match *self {
634 clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()),
635 clean::Return(ref ty) => write!(f, " -&gt; {}", ty),
85aaf69f 636 clean::DefaultReturn => Ok(()),
1a4d82fc
JJ
637 }
638 }
639}
640
85aaf69f 641impl fmt::Display for clean::FnDecl {
1a4d82fc 642 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
e9174d1e
SL
643 if self.variadic {
644 write!(f, "({args}, ...){arrow}", args = self.inputs, arrow = self.output)
645 } else {
646 write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output)
647 }
1a4d82fc
JJ
648 }
649}
650
85aaf69f 651impl<'a> fmt::Display for Method<'a> {
1a4d82fc 652 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
a7813a04 653 let decl = self.0;
1a4d82fc 654 let mut args = String::new();
a7813a04 655 for (i, input) in decl.inputs.values.iter().enumerate() {
9346a6ac 656 if i > 0 || !args.is_empty() { args.push_str(", "); }
a7813a04
XL
657 if let Some(selfty) = input.to_self() {
658 match selfty {
659 clean::SelfValue => args.push_str("self"),
660 clean::SelfBorrowed(Some(ref lt), mtbl) => {
661 args.push_str(&format!("&amp;{} {}self", *lt, MutableSpace(mtbl)));
662 }
663 clean::SelfBorrowed(None, mtbl) => {
664 args.push_str(&format!("&amp;{}self", MutableSpace(mtbl)));
665 }
666 clean::SelfExplicit(ref typ) => {
667 args.push_str(&format!("self: {}", *typ));
668 }
669 }
670 } else {
671 if !input.name.is_empty() {
672 args.push_str(&format!("{}: ", input.name));
673 }
674 args.push_str(&format!("{}", input.type_));
1a4d82fc 675 }
1a4d82fc 676 }
a7813a04 677 write!(f, "({args}){arrow}", args = args, arrow = decl.output)
1a4d82fc
JJ
678 }
679}
680
54a0048b 681impl<'a> fmt::Display for VisSpace<'a> {
1a4d82fc 682 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54a0048b 683 match *self.get() {
a7813a04
XL
684 Some(clean::Public) => write!(f, "pub "),
685 Some(clean::Inherited) | None => Ok(())
1a4d82fc
JJ
686 }
687 }
688}
689
85aaf69f 690impl fmt::Display for UnsafetySpace {
1a4d82fc
JJ
691 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
692 match self.get() {
e9174d1e
SL
693 hir::Unsafety::Unsafe => write!(f, "unsafe "),
694 hir::Unsafety::Normal => Ok(())
1a4d82fc
JJ
695 }
696 }
697}
698
62682a34
SL
699impl fmt::Display for ConstnessSpace {
700 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
701 match self.get() {
e9174d1e
SL
702 hir::Constness::Const => write!(f, "const "),
703 hir::Constness::NotConst => Ok(())
62682a34
SL
704 }
705 }
706}
707
85aaf69f 708impl fmt::Display for clean::Import {
1a4d82fc
JJ
709 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
710 match *self {
711 clean::SimpleImport(ref name, ref src) => {
a7813a04 712 if *name == src.path.last_name() {
1a4d82fc
JJ
713 write!(f, "use {};", *src)
714 } else {
715 write!(f, "use {} as {};", *src, *name)
716 }
717 }
718 clean::GlobImport(ref src) => {
719 write!(f, "use {}::*;", *src)
720 }
721 clean::ImportList(ref src, ref names) => {
54a0048b 722 write!(f, "use {}::{{", *src)?;
1a4d82fc
JJ
723 for (i, n) in names.iter().enumerate() {
724 if i > 0 {
54a0048b 725 write!(f, ", ")?;
1a4d82fc 726 }
54a0048b 727 write!(f, "{}", *n)?;
1a4d82fc
JJ
728 }
729 write!(f, "}};")
730 }
731 }
732 }
733}
734
85aaf69f 735impl fmt::Display for clean::ImportSource {
1a4d82fc
JJ
736 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
737 match self.did {
738 Some(did) => resolved_path(f, did, &self.path, true),
739 _ => {
740 for (i, seg) in self.path.segments.iter().enumerate() {
741 if i > 0 {
54a0048b 742 write!(f, "::")?
1a4d82fc 743 }
54a0048b 744 write!(f, "{}", seg.name)?;
1a4d82fc
JJ
745 }
746 Ok(())
747 }
748 }
749 }
750}
751
85aaf69f 752impl fmt::Display for clean::ViewListIdent {
1a4d82fc
JJ
753 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
754 match self.source {
755 Some(did) => {
9346a6ac 756 let path = clean::Path::singleton(self.name.clone());
54a0048b 757 resolved_path(f, did, &path, false)?;
1a4d82fc 758 }
54a0048b 759 _ => write!(f, "{}", self.name)?,
1a4d82fc 760 }
e9174d1e
SL
761
762 if let Some(ref name) = self.rename {
54a0048b 763 write!(f, " as {}", name)?;
e9174d1e
SL
764 }
765 Ok(())
1a4d82fc
JJ
766 }
767}
768
85aaf69f 769impl fmt::Display for clean::TypeBinding {
1a4d82fc
JJ
770 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
771 write!(f, "{}={}", self.name, self.ty)
772 }
773}
774
85aaf69f 775impl fmt::Display for MutableSpace {
1a4d82fc
JJ
776 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
777 match *self {
778 MutableSpace(clean::Immutable) => Ok(()),
779 MutableSpace(clean::Mutable) => write!(f, "mut "),
780 }
781 }
782}
783
85aaf69f 784impl fmt::Display for RawMutableSpace {
1a4d82fc
JJ
785 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
786 match *self {
787 RawMutableSpace(clean::Immutable) => write!(f, "const "),
788 RawMutableSpace(clean::Mutable) => write!(f, "mut "),
789 }
790 }
791}
792
9346a6ac
AL
793impl fmt::Display for AbiSpace {
794 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
795 match self.0 {
796 Abi::Rust => Ok(()),
797 Abi::C => write!(f, "extern "),
a7813a04 798 abi => write!(f, "extern &quot;{}&quot; ", abi.name()),
9346a6ac
AL
799 }
800 }
801}