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.
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.
11 //! HTML formatting module
13 //! This module contains a large number of `fmt::Display` implementations for
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.
19 use std
::iter
::repeat
;
21 use rustc
::hir
::def_id
::DefId
;
25 use clean
::{self, PrimitiveType}
;
26 use core
::DocAccessLevels
;
27 use html
::item_type
::ItemType
;
29 use html
::render
::{cache, CURRENT_LOCATION_KEY}
;
31 /// Helper to render an optional visibility with a space after it (if the
32 /// visibility is preset)
33 #[derive(Copy, Clone)]
34 pub struct VisSpace
<'a
>(pub &'a Option
<clean
::Visibility
>);
35 /// Similarly to VisSpace, this structure is used to render a function style with a
37 #[derive(Copy, Clone)]
38 pub struct UnsafetySpace(pub hir
::Unsafety
);
39 /// Similarly to VisSpace, this structure is used to render a function constness
40 /// with a space after it.
41 #[derive(Copy, Clone)]
42 pub struct ConstnessSpace(pub hir
::Constness
);
43 /// Similar to VisSpace, but used for mutability
44 #[derive(Copy, Clone)]
45 pub struct MutableSpace(pub clean
::Mutability
);
46 /// Similar to VisSpace, but used for mutability
47 #[derive(Copy, Clone)]
48 pub struct RawMutableSpace(pub clean
::Mutability
);
49 /// Wrapper struct for emitting type parameter bounds.
50 pub struct TyParamBounds
<'a
>(pub &'a
[clean
::TyParamBound
]);
51 /// Wrapper struct for emitting a comma-separated list of items
52 pub struct CommaSep
<'a
, T
: 'a
>(pub &'a
[T
]);
53 pub struct AbiSpace(pub Abi
);
55 /// Wrapper struct for properly emitting a method declaration.
56 pub struct Method
<'a
> {
57 /// The declaration to emit.
58 pub decl
: &'a clean
::FnDecl
,
59 /// The length of the function's "name", used to determine line-wrapping.
61 /// The number of spaces to indent each successive line with, if line-wrapping is necessary.
65 /// Wrapper struct for emitting a where clause from Generics.
66 pub struct WhereClause
<'a
>{
67 /// The Generics from which to emit a where clause.
68 pub gens
: &'a clean
::Generics
,
69 /// The number of spaces to indent each line with.
71 /// Whether the where clause needs to add a comma and newline after the last bound.
72 pub end_newline
: bool
,
80 impl<'a
> VisSpace
<'a
> {
81 pub fn get(self) -> &'a Option
<clean
::Visibility
> {
82 let VisSpace(v
) = self; v
87 pub fn get(&self) -> hir
::Unsafety
{
88 let UnsafetySpace(v
) = *self; v
93 pub fn get(&self) -> hir
::Constness
{
94 let ConstnessSpace(v
) = *self; v
98 impl<'a
, T
: fmt
::Display
> fmt
::Display
for CommaSep
<'a
, T
> {
99 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
100 for (i
, item
) in self.0.iter
().enumerate() {
101 if i
!= 0 { write!(f, ", ")?; }
102 fmt
::Display
::fmt(item
, f
)?
;
108 impl<'a
> fmt
::Display
for TyParamBounds
<'a
> {
109 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
110 let &TyParamBounds(bounds
) = self;
111 for (i
, bound
) in bounds
.iter().enumerate() {
115 fmt
::Display
::fmt(bound
, f
)?
;
121 impl fmt
::Display
for clean
::Generics
{
122 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
123 if self.lifetimes
.is_empty() && self.type_params
.is_empty() { return Ok(()) }
127 f
.write_str("<")?
;
130 for (i
, life
) in self.lifetimes
.iter().enumerate() {
134 write
!(f
, "{}", *life
)?
;
137 if !self.type_params
.is_empty() {
138 if !self.lifetimes
.is_empty() {
141 for (i
, tp
) in self.type_params
.iter().enumerate() {
145 f
.write_str(&tp
.name
)?
;
147 if !tp
.bounds
.is_empty() {
149 write
!(f
, ": {:#}", TyParamBounds(&tp
.bounds
))?
;
151 write
!(f
, ": {}", TyParamBounds(&tp
.bounds
))?
;
155 if let Some(ref ty
) = tp
.default {
157 write
!(f
, " = {:#}", ty
)?
;
159 write
!(f
, " = {}", ty
)?
;
167 f
.write_str(">")?
;
173 impl<'a
> fmt
::Display
for WhereClause
<'a
> {
174 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
175 let &WhereClause { gens, indent, end_newline }
= self;
176 if gens
.where_predicates
.is_empty() {
179 let mut clause
= String
::new();
181 clause
.push_str(" where");
184 clause
.push_str(" <span class=\"where fmt-newline\">where");
186 clause
.push_str(" <span class=\"where\">where");
189 for (i
, pred
) in gens
.where_predicates
.iter().enumerate() {
193 clause
.push_str("<br>");
197 &clean
::WherePredicate
::BoundPredicate { ref ty, ref bounds }
=> {
200 clause
.push_str(&format
!("{:#}: {:#}", ty
, TyParamBounds(bounds
)));
202 clause
.push_str(&format
!("{}: {}", ty
, TyParamBounds(bounds
)));
205 &clean
::WherePredicate
::RegionPredicate
{ ref lifetime
,
207 clause
.push_str(&format
!("{}: ", lifetime
));
208 for (i
, lifetime
) in bounds
.iter().enumerate() {
210 clause
.push_str(" + ");
213 clause
.push_str(&format
!("{}", lifetime
));
216 &clean
::WherePredicate
::EqPredicate { ref lhs, ref rhs }
=> {
218 clause
.push_str(&format
!("{:#} == {:#}", lhs
, rhs
));
220 clause
.push_str(&format
!("{} == {}", lhs
, rhs
));
225 if i
< gens
.where_predicates
.len() - 1 || end_newline
{
231 // add a space so stripping <br> tags and breaking spaces still renders properly
235 clause
.push_str(" ");
240 clause
.push_str("</span>");
241 let padding
= repeat(" ").take(indent
+ 4).collect
::<String
>();
242 clause
= clause
.replace("<br>", &format
!("<br>{}", padding
));
243 clause
.insert_str(0, &repeat(" ").take(indent
.saturating_sub(1))
244 .collect
::<String
>());
246 clause
.insert_str(0, "<br>");
249 write
!(f
, "{}", clause
)
253 impl fmt
::Display
for clean
::Lifetime
{
254 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
255 f
.write_str(self.get_ref())?
;
260 impl fmt
::Display
for clean
::PolyTrait
{
261 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
262 if !self.lifetimes
.is_empty() {
264 f
.write_str("for<")?
;
266 f
.write_str("for<")?
;
268 for (i
, lt
) in self.lifetimes
.iter().enumerate() {
272 write
!(f
, "{}", lt
)?
;
277 f
.write_str("> ")?
;
281 write
!(f
, "{:#}", self.trait_
)
283 write
!(f
, "{}", self.trait_
)
288 impl fmt
::Display
for clean
::TyParamBound
{
289 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
291 clean
::RegionBound(ref lt
) => {
294 clean
::TraitBound(ref ty
, modifier
) => {
295 let modifier_str
= match modifier
{
296 hir
::TraitBoundModifier
::None
=> "",
297 hir
::TraitBoundModifier
::Maybe
=> "?",
300 write
!(f
, "{}{:#}", modifier_str
, *ty
)
302 write
!(f
, "{}{}", modifier_str
, *ty
)
309 impl fmt
::Display
for clean
::PathParameters
{
310 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
312 clean
::PathParameters
::AngleBracketed
{
313 ref lifetimes
, ref types
, ref bindings
315 if !lifetimes
.is_empty() || !types
.is_empty() || !bindings
.is_empty() {
319 f
.write_str("<")?
;
321 let mut comma
= false;
322 for lifetime
in lifetimes
{
327 write
!(f
, "{}", *lifetime
)?
;
335 write
!(f
, "{:#}", *ty
)?
;
337 write
!(f
, "{}", *ty
)?
;
340 for binding
in bindings
{
346 write
!(f
, "{:#}", *binding
)?
;
348 write
!(f
, "{}", *binding
)?
;
354 f
.write_str(">")?
;
358 clean
::PathParameters
::Parenthesized { ref inputs, ref output }
=> {
360 let mut comma
= false;
367 write
!(f
, "{:#}", *ty
)?
;
369 write
!(f
, "{}", *ty
)?
;
373 if let Some(ref ty
) = *output
{
375 write
!(f
, " -> {:#}", ty
)?
;
377 write
!(f
, " -> {}", ty
)?
;
386 impl fmt
::Display
for clean
::PathSegment
{
387 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
388 f
.write_str(&self.name
)?
;
390 write
!(f
, "{:#}", self.params
)
392 write
!(f
, "{}", self.params
)
397 impl fmt
::Display
for clean
::Path
{
398 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
403 for (i
, seg
) in self.segments
.iter().enumerate() {
408 write
!(f
, "{:#}", seg
)?
;
410 write
!(f
, "{}", seg
)?
;
417 pub fn href(did
: DefId
) -> Option
<(String
, ItemType
, Vec
<String
>)> {
419 if !did
.is_local() && !cache
.access_levels
.is_doc_reachable(did
) {
423 let loc
= CURRENT_LOCATION_KEY
.with(|l
| l
.borrow().clone());
424 let (fqp
, shortty
, mut url
) = match cache
.paths
.get(&did
) {
425 Some(&(ref fqp
, shortty
)) => {
426 (fqp
, shortty
, repeat("../").take(loc
.len()).collect())
428 None
=> match cache
.external_paths
.get(&did
) {
429 Some(&(ref fqp
, shortty
)) => {
430 (fqp
, shortty
, match cache
.extern_locations
[&did
.krate
] {
431 (.., render
::Remote(ref s
)) => s
.to_string(),
432 (.., render
::Local
) => repeat("../").take(loc
.len()).collect(),
433 (.., render
::Unknown
) => return None
,
439 for component
in &fqp
[..fqp
.len() - 1] {
440 url
.push_str(component
);
444 ItemType
::Module
=> {
445 url
.push_str(fqp
.last().unwrap());
446 url
.push_str("/index.html");
449 url
.push_str(shortty
.css_class());
451 url
.push_str(fqp
.last().unwrap());
452 url
.push_str(".html");
455 Some((url
, shortty
, fqp
.to_vec()))
458 /// Used when rendering a `ResolvedPath` structure. This invokes the `path`
459 /// rendering function with the necessary arguments for linking to a local path.
460 fn resolved_path(w
: &mut fmt
::Formatter
, did
: DefId
, path
: &clean
::Path
,
461 print_all
: bool
, use_absolute
: bool
) -> fmt
::Result
{
462 let last
= path
.segments
.last().unwrap();
463 let rel_root
= match &*path
.segments
[0].name
{
464 "self" => Some("./".to_string()),
469 let amt
= path
.segments
.len() - 1;
472 for seg
in &path
.segments
[..amt
] {
473 if "super" == seg
.name
|| "self" == seg
.name
|| w
.alternate() {
474 write
!(w
, "{}::", seg
.name
)?
;
476 root
.push_str(&seg
.name
);
478 write
!(w
, "<a class=\"mod\" href=\"{}index.html\">{}</a>::",
485 for seg
in &path
.segments
[..amt
] {
486 write
!(w
, "{}::", seg
.name
)?
;
492 write
!(w
, "{:#}{:#}", HRef
::new(did
, &last
.name
), last
.params
)?
;
494 let path
= if use_absolute
{
496 Some((_
, _
, fqp
)) => {
498 fqp
[..fqp
.len() - 1].join("::"),
499 HRef
::new(did
, fqp
.last().unwrap()))
501 None
=> format
!("{}", HRef
::new(did
, &last
.name
)),
504 format
!("{}", HRef
::new(did
, &last
.name
))
506 write
!(w
, "{}{}", path
, last
.params
)?
;
511 fn primitive_link(f
: &mut fmt
::Formatter
,
512 prim
: clean
::PrimitiveType
,
513 name
: &str) -> fmt
::Result
{
515 let mut needs_termination
= false;
517 match m
.primitive_locations
.get(&prim
) {
518 Some(&def_id
) if def_id
.is_local() => {
519 let len
= CURRENT_LOCATION_KEY
.with(|s
| s
.borrow().len());
520 let len
= if len
== 0 {0}
else {len - 1}
;
521 write
!(f
, "<a class=\"primitive\" href=\"{}primitive.{}.html\">",
522 repeat("../").take(len
).collect
::<String
>(),
524 needs_termination
= true;
527 let loc
= match m
.extern_locations
[&def_id
.krate
] {
528 (ref cname
, _
, render
::Remote(ref s
)) => {
529 Some((cname
, s
.to_string()))
531 (ref cname
, _
, render
::Local
) => {
532 let len
= CURRENT_LOCATION_KEY
.with(|s
| s
.borrow().len());
533 Some((cname
, repeat("../").take(len
).collect
::<String
>()))
535 (.., render
::Unknown
) => None
,
537 if let Some((cname
, root
)) = loc
{
538 write
!(f
, "<a class=\"primitive\" href=\"{}{}/primitive.{}.html\">",
542 needs_termination
= true;
548 write
!(f
, "{}", name
)?
;
549 if needs_termination
{
555 /// Helper to render type parameters
556 fn tybounds(w
: &mut fmt
::Formatter
,
557 typarams
: &Option
<Vec
<clean
::TyParamBound
>>) -> fmt
::Result
{
559 Some(ref params
) => {
560 for param
in params
{
562 fmt
::Display
::fmt(param
, w
)?
;
571 pub fn new(did
: DefId
, text
: &'a
str) -> HRef
<'a
> {
572 HRef { did: did, text: text }
576 impl<'a
> fmt
::Display
for HRef
<'a
> {
577 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
578 match href(self.did
) {
579 Some((url
, shortty
, fqp
)) => if !f
.alternate() {
580 write
!(f
, "<a class=\"{}\" href=\"{}\" title=\"{} {}\">{}</a>",
581 shortty
, url
, shortty
, fqp
.join("::"), self.text
)
583 write
!(f
, "{}", self.text
)
585 _
=> write
!(f
, "{}", self.text
),
590 fn fmt_type(t
: &clean
::Type
, f
: &mut fmt
::Formatter
, use_absolute
: bool
) -> fmt
::Result
{
592 clean
::Generic(ref name
) => {
595 clean
::ResolvedPath{ did, ref typarams, ref path, is_generic }
=> {
596 // Paths like T::Output and Self::Output should be rendered with all segments
597 resolved_path(f
, did
, path
, is_generic
, use_absolute
)?
;
598 tybounds(f
, typarams
)
600 clean
::Infer
=> write
!(f
, "_"),
601 clean
::Primitive(prim
) => primitive_link(f
, prim
, prim
.as_str()),
602 clean
::BareFunction(ref decl
) => {
604 write
!(f
, "{}{}fn{:#}{:#}",
605 UnsafetySpace(decl
.unsafety
),
610 write
!(f
, "{}{}", UnsafetySpace(decl
.unsafety
), AbiSpace(decl
.abi
))?
;
611 primitive_link(f
, PrimitiveType
::Fn
, "fn")?
;
612 write
!(f
, "{}{}", decl
.generics
, decl
.decl
)
615 clean
::Tuple(ref typs
) => {
617 &[] => primitive_link(f
, PrimitiveType
::Unit
, "()"),
619 primitive_link(f
, PrimitiveType
::Tuple
, "(")?
;
620 //carry f.alternate() into this display w/o branching manually
621 fmt
::Display
::fmt(one
, f
)?
;
622 primitive_link(f
, PrimitiveType
::Tuple
, ",)")
625 primitive_link(f
, PrimitiveType
::Tuple
, "(")?
;
626 fmt
::Display
::fmt(&CommaSep(&many
), f
)?
;
627 primitive_link(f
, PrimitiveType
::Tuple
, ")")
631 clean
::Slice(ref t
) => {
632 primitive_link(f
, PrimitiveType
::Slice
, "[")?
;
633 fmt
::Display
::fmt(t
, f
)?
;
634 primitive_link(f
, PrimitiveType
::Slice
, "]")
636 clean
::Array(ref t
, ref n
) => {
637 primitive_link(f
, PrimitiveType
::Array
, "[")?
;
638 fmt
::Display
::fmt(t
, f
)?
;
639 primitive_link(f
, PrimitiveType
::Array
, &format
!("; {}]", n
))
641 clean
::Never
=> f
.write_str("!"),
642 clean
::RawPointer(m
, ref t
) => {
644 clean
::Generic(_
) | clean
::ResolvedPath {is_generic: true, ..}
=> {
646 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
647 &format
!("*{}{:#}", RawMutableSpace(m
), t
))
649 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
650 &format
!("*{}{}", RawMutableSpace(m
), t
))
654 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
655 &format
!("*{}", RawMutableSpace(m
)))?
;
656 fmt
::Display
::fmt(t
, f
)
660 clean
::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty}
=> {
662 Some(ref l
) => format
!("{} ", *l
),
665 let m
= MutableSpace(mutability
);
666 let amp
= if f
.alternate() {
672 clean
::Slice(ref bt
) => { // BorrowedRef{ ... Slice(T) } is
&[T
]
674 clean
::Generic(_
) => {
676 primitive_link(f
, PrimitiveType
::Slice
,
677 &format
!("{}{}{}[{:#}]", amp
, lt
, m
, **bt
))
679 primitive_link(f
, PrimitiveType
::Slice
,
680 &format
!("{}{}{}[{}]", amp
, lt
, m
, **bt
))
684 primitive_link(f
, PrimitiveType
::Slice
,
685 &format
!("{}{}{}[", amp
, lt
, m
))?
;
687 write
!(f
, "{:#}", **bt
)?
;
689 write
!(f
, "{}", **bt
)?
;
691 primitive_link(f
, PrimitiveType
::Slice
, "]")
695 clean
::ResolvedPath { typarams: Some(ref v), .. }
if !v
.is_empty() => {
696 write
!(f
, "{}{}{}(", amp
, lt
, m
)?
;
697 fmt_type(&ty
, f
, use_absolute
)?
;
700 clean
::Generic(..) => {
701 primitive_link(f
, PrimitiveType
::Reference
,
702 &format
!("{}{}{}", amp
, lt
, m
))?
;
703 fmt_type(&ty
, f
, use_absolute
)
706 write
!(f
, "{}{}{}", amp
, lt
, m
)?
;
707 fmt_type(&ty
, f
, use_absolute
)
711 clean
::ImplTrait(ref bounds
) => {
713 for (i
, bound
) in bounds
.iter().enumerate() {
718 write
!(f
, "{:#}", *bound
)?
;
720 write
!(f
, "{}", *bound
)?
;
725 clean
::QPath { ref name, ref self_type, ref trait_ }
=> {
726 let should_show_cast
= match *trait_
{
727 box clean
::ResolvedPath { ref path, .. }
=> {
728 !path
.segments
.is_empty() && !self_type
.is_self_type()
733 if should_show_cast
{
734 write
!(f
, "<{:#} as {:#}>::", self_type
, trait_
)?
736 write
!(f
, "{:#}::", self_type
)?
739 if should_show_cast
{
740 write
!(f
, "<{} as {}>::", self_type
, trait_
)?
742 write
!(f
, "{}::", self_type
)?
746 // It's pretty unsightly to look at `<A as B>::C` in output, and
747 // we've got hyperlinking on our side, so try to avoid longer
748 // notation as much as possible by making `C` a hyperlink to trait
749 // `B` to disambiguate.
751 // FIXME: this is still a lossy conversion and there should probably
752 // be a better way of representing this in general? Most of
753 // the ugliness comes from inlining across crates where
754 // everything comes in as a fully resolved QPath (hard to
756 box clean
::ResolvedPath { did, ref typarams, .. }
=> {
758 Some((ref url
, _
, ref path
)) if !f
.alternate() => {
760 "<a class=\"type\" href=\"{url}#{shortty}.{name}\" \
761 title=\"type {path}::{name}\">{name}</a>",
763 shortty
= ItemType
::AssociatedType
,
765 path
= path
.join("::"))?
;
767 _
=> write
!(f
, "{}", name
)?
,
770 // FIXME: `typarams` are not rendered, and this seems bad?
775 write
!(f
, "{}", name
)
779 clean
::Unique(..) => {
780 panic
!("should have been cleaned")
785 impl fmt
::Display
for clean
::Type
{
786 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
787 fmt_type(self, f
, false)
791 fn fmt_impl(i
: &clean
::Impl
,
792 f
: &mut fmt
::Formatter
,
794 use_absolute
: bool
) -> fmt
::Result
{
796 write
!(f
, "impl{:#} ", i
.generics
)?
;
798 write
!(f
, "impl{} ", i
.generics
)?
;
801 if let Some(ref ty
) = i
.trait_
{
802 if i
.polarity
== Some(clean
::ImplPolarity
::Negative
) {
807 fmt
::Display
::fmt(ty
, f
)?
;
810 clean
::ResolvedPath { typarams: None, ref path, is_generic: false, .. }
=> {
811 let last
= path
.segments
.last().unwrap();
812 fmt
::Display
::fmt(&last
.name
, f
)?
;
813 fmt
::Display
::fmt(&last
.params
, f
)?
;
821 fmt_type(&i
.for_
, f
, use_absolute
)?
;
823 fmt
::Display
::fmt(&WhereClause { gens: &i.generics, indent: 0, end_newline: true }
, f
)?
;
827 impl fmt
::Display
for clean
::Impl
{
828 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
829 fmt_impl(self, f
, true, false)
833 // The difference from above is that trait is not hyperlinked.
834 pub fn fmt_impl_for_trait_page(i
: &clean
::Impl
,
835 f
: &mut fmt
::Formatter
,
836 use_absolute
: bool
) -> fmt
::Result
{
837 fmt_impl(i
, f
, false, use_absolute
)
840 impl fmt
::Display
for clean
::Arguments
{
841 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
842 for (i
, input
) in self.values
.iter().enumerate() {
843 if !input
.name
.is_empty() {
844 write
!(f
, "{}: ", input
.name
)?
;
847 write
!(f
, "{:#}", input
.type_
)?
;
849 write
!(f
, "{}", input
.type_
)?
;
851 if i
+ 1 < self.values
.len() { write!(f, ", ")?; }
857 impl fmt
::Display
for clean
::FunctionRetTy
{
858 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
860 clean
::Return(clean
::Tuple(ref tys
)) if tys
.is_empty() => Ok(()),
861 clean
::Return(ref ty
) if f
.alternate() => write
!(f
, " -> {:#}", ty
),
862 clean
::Return(ref ty
) => write
!(f
, " -> {}", ty
),
863 clean
::DefaultReturn
=> Ok(()),
868 impl fmt
::Display
for clean
::FnDecl
{
869 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
872 write
!(f
, "({args:#}, ...){arrow:#}", args
= self.inputs
, arrow
= self.output
)
874 write
!(f
, "({args}, ...){arrow}", args
= self.inputs
, arrow
= self.output
)
878 write
!(f
, "({args:#}){arrow:#}", args
= self.inputs
, arrow
= self.output
)
880 write
!(f
, "({args}){arrow}", args
= self.inputs
, arrow
= self.output
)
886 impl<'a
> fmt
::Display
for Method
<'a
> {
887 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
888 let &Method { decl, name_len, indent }
= self;
889 let amp
= if f
.alternate() { "&" }
else { "&" }
;
890 let mut args
= String
::new();
891 let mut args_plain
= String
::new();
892 for (i
, input
) in decl
.inputs
.values
.iter().enumerate() {
894 args
.push_str("<br>");
897 if let Some(selfty
) = input
.to_self() {
899 clean
::SelfValue
=> {
900 args
.push_str("self");
901 args_plain
.push_str("self");
903 clean
::SelfBorrowed(Some(ref lt
), mtbl
) => {
904 args
.push_str(&format
!("{}{} {}self", amp
, *lt
, MutableSpace(mtbl
)));
905 args_plain
.push_str(&format
!("&{} {}self", *lt
, MutableSpace(mtbl
)));
907 clean
::SelfBorrowed(None
, mtbl
) => {
908 args
.push_str(&format
!("{}{}self", amp
, MutableSpace(mtbl
)));
909 args_plain
.push_str(&format
!("&{}self", MutableSpace(mtbl
)));
911 clean
::SelfExplicit(ref typ
) => {
913 args
.push_str(&format
!("self: {:#}", *typ
));
915 args
.push_str(&format
!("self: {}", *typ
));
917 args_plain
.push_str(&format
!("self: {:#}", *typ
));
922 args
.push_str(" <br>");
923 args_plain
.push_str(" ");
925 if !input
.name
.is_empty() {
926 args
.push_str(&format
!("{}: ", input
.name
));
927 args_plain
.push_str(&format
!("{}: ", input
.name
));
931 args
.push_str(&format
!("{:#}", input
.type_
));
933 args
.push_str(&format
!("{}", input
.type_
));
935 args_plain
.push_str(&format
!("{:#}", input
.type_
));
937 if i
+ 1 < decl
.inputs
.values
.len() {
939 args_plain
.push('
,'
);
944 args
.push_str(",<br> ...");
945 args_plain
.push_str(", ...");
948 let arrow_plain
= format
!("{:#}", decl
.output
);
949 let arrow
= if f
.alternate() {
950 format
!("{:#}", decl
.output
)
952 format
!("{}", decl
.output
)
955 let pad
= repeat(" ").take(name_len
).collect
::<String
>();
956 let plain
= format
!("{pad}({args}){arrow}",
959 arrow
= arrow_plain
);
961 let output
= if plain
.len() > 80 {
962 let full_pad
= format
!("<br>{}", repeat(" ").take(indent
+ 4).collect
::<String
>());
963 let close_pad
= format
!("<br>{}", repeat(" ").take(indent
).collect
::<String
>());
964 format
!("({args}{close}){arrow}",
965 args
= args
.replace("<br>", &full_pad
),
969 format
!("({args}){arrow}", args
= args
.replace("<br>", ""), arrow
= arrow
)
973 write
!(f
, "{}", output
.replace("<br>", "\n"))
975 write
!(f
, "{}", output
)
980 impl<'a
> fmt
::Display
for VisSpace
<'a
> {
981 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
983 Some(clean
::Public
) => write
!(f
, "pub "),
984 Some(clean
::Inherited
) | None
=> Ok(())
989 impl fmt
::Display
for UnsafetySpace
{
990 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
992 hir
::Unsafety
::Unsafe
=> write
!(f
, "unsafe "),
993 hir
::Unsafety
::Normal
=> Ok(())
998 impl fmt
::Display
for ConstnessSpace
{
999 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1001 hir
::Constness
::Const
=> write
!(f
, "const "),
1002 hir
::Constness
::NotConst
=> Ok(())
1007 impl fmt
::Display
for clean
::Import
{
1008 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1010 clean
::Import
::Simple(ref name
, ref src
) => {
1011 if *name
== src
.path
.last_name() {
1012 write
!(f
, "use {};", *src
)
1014 write
!(f
, "use {} as {};", *src
, *name
)
1017 clean
::Import
::Glob(ref src
) => {
1018 if src
.path
.segments
.is_empty() {
1021 write
!(f
, "use {}::*;", *src
)
1028 impl fmt
::Display
for clean
::ImportSource
{
1029 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1031 Some(did
) => resolved_path(f
, did
, &self.path
, true, false),
1033 for (i
, seg
) in self.path
.segments
.iter().enumerate() {
1037 write
!(f
, "{}", seg
.name
)?
;
1045 impl fmt
::Display
for clean
::TypeBinding
{
1046 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1048 write
!(f
, "{} = {:#}", self.name
, self.ty
)
1050 write
!(f
, "{} = {}", self.name
, self.ty
)
1055 impl fmt
::Display
for MutableSpace
{
1056 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1058 MutableSpace(clean
::Immutable
) => Ok(()),
1059 MutableSpace(clean
::Mutable
) => write
!(f
, "mut "),
1064 impl fmt
::Display
for RawMutableSpace
{
1065 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1067 RawMutableSpace(clean
::Immutable
) => write
!(f
, "const "),
1068 RawMutableSpace(clean
::Mutable
) => write
!(f
, "mut "),
1073 impl fmt
::Display
for AbiSpace
{
1074 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1075 let quot
= if f
.alternate() { "\"" }
else { """ }
;
1077 Abi
::Rust
=> Ok(()),
1078 abi
=> write
!(f
, "extern {0}{1}{0} ", quot
, abi
.name()),