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.
20 use rustc
::hir
::def_id
::DefId
;
21 use rustc_target
::spec
::abi
::Abi
;
24 use clean
::{self, PrimitiveType}
;
25 use core
::DocAccessLevels
;
26 use html
::item_type
::ItemType
;
27 use html
::render
::{self, cache, CURRENT_LOCATION_KEY}
;
29 /// Helper to render an optional visibility with a space after it (if the
30 /// visibility is preset)
31 #[derive(Copy, Clone)]
32 pub struct VisSpace
<'a
>(pub &'a Option
<clean
::Visibility
>);
33 /// Similarly to VisSpace, this structure is used to render a function style with a
35 #[derive(Copy, Clone)]
36 pub struct UnsafetySpace(pub hir
::Unsafety
);
37 /// Similarly to VisSpace, this structure is used to render a function constness
38 /// with a space after it.
39 #[derive(Copy, Clone)]
40 pub struct ConstnessSpace(pub hir
::Constness
);
41 /// Similarly to VisSpace, this structure is used to render a function asyncness
42 /// with a space after it.
43 #[derive(Copy, Clone)]
44 pub struct AsyncSpace(pub hir
::IsAsync
);
45 /// Similar to VisSpace, but used for mutability
46 #[derive(Copy, Clone)]
47 pub struct MutableSpace(pub clean
::Mutability
);
48 /// Similar to VisSpace, but used for mutability
49 #[derive(Copy, Clone)]
50 pub struct RawMutableSpace(pub clean
::Mutability
);
51 /// Wrapper struct for emitting type parameter bounds.
52 pub struct GenericBounds
<'a
>(pub &'a
[clean
::GenericBound
]);
53 /// Wrapper struct for emitting a comma-separated list of items
54 pub struct CommaSep
<'a
, T
: 'a
>(pub &'a
[T
]);
55 pub struct AbiSpace(pub Abi
);
57 /// Wrapper struct for properly emitting a method declaration.
58 pub struct Method
<'a
> {
59 /// The declaration to emit.
60 pub decl
: &'a clean
::FnDecl
,
61 /// The length of the function's "name", used to determine line-wrapping.
63 /// The number of spaces to indent each successive line with, if line-wrapping is necessary.
67 /// Wrapper struct for emitting a where clause from Generics.
68 pub struct WhereClause
<'a
>{
69 /// The Generics from which to emit a where clause.
70 pub gens
: &'a clean
::Generics
,
71 /// The number of spaces to indent each line with.
73 /// Whether the where clause needs to add a comma and newline after the last bound.
74 pub end_newline
: bool
,
82 impl<'a
> VisSpace
<'a
> {
83 pub fn get(self) -> &'a Option
<clean
::Visibility
> {
84 let VisSpace(v
) = self; v
89 pub fn get(&self) -> hir
::Unsafety
{
90 let UnsafetySpace(v
) = *self; v
95 pub fn get(&self) -> hir
::Constness
{
96 let ConstnessSpace(v
) = *self; v
100 impl<'a
, T
: fmt
::Display
> fmt
::Display
for CommaSep
<'a
, T
> {
101 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
102 for (i
, item
) in self.0.iter
().enumerate() {
103 if i
!= 0 { write!(f, ", ")?; }
104 fmt
::Display
::fmt(item
, f
)?
;
110 impl<'a
> fmt
::Display
for GenericBounds
<'a
> {
111 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
112 let &GenericBounds(bounds
) = self;
113 for (i
, bound
) in bounds
.iter().enumerate() {
117 fmt
::Display
::fmt(bound
, f
)?
;
123 impl fmt
::Display
for clean
::GenericParamDef
{
124 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
126 clean
::GenericParamDefKind
::Lifetime
=> write
!(f
, "{}", self.name
),
127 clean
::GenericParamDefKind
::Type { ref bounds, ref default, .. }
=> {
128 f
.write_str(&self.name
)?
;
130 if !bounds
.is_empty() {
132 write
!(f
, ": {:#}", GenericBounds(bounds
))?
;
134 write
!(f
, ": {}", GenericBounds(bounds
))?
;
138 if let Some(ref ty
) = default {
140 write
!(f
, " = {:#}", ty
)?
;
142 write
!(f
, " = {}", ty
)?
;
152 impl fmt
::Display
for clean
::Generics
{
153 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
154 let real_params
= self.params
156 .filter(|p
| !p
.is_synthetic_type_param())
157 .collect
::<Vec
<_
>>();
158 if real_params
.is_empty() {
162 write
!(f
, "<{:#}>", CommaSep(&real_params
))
164 write
!(f
, "<{}>", CommaSep(&real_params
))
169 impl<'a
> fmt
::Display
for WhereClause
<'a
> {
170 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
171 let &WhereClause { gens, indent, end_newline }
= self;
172 if gens
.where_predicates
.is_empty() {
175 let mut clause
= String
::new();
177 clause
.push_str(" where");
180 clause
.push_str(" <span class=\"where fmt-newline\">where");
182 clause
.push_str(" <span class=\"where\">where");
185 for (i
, pred
) in gens
.where_predicates
.iter().enumerate() {
189 clause
.push_str("<br>");
193 &clean
::WherePredicate
::BoundPredicate { ref ty, ref bounds }
=> {
196 clause
.push_str(&format
!("{:#}: {:#}", ty
, GenericBounds(bounds
)));
198 clause
.push_str(&format
!("{}: {}", ty
, GenericBounds(bounds
)));
201 &clean
::WherePredicate
::RegionPredicate
{ ref lifetime
,
203 clause
.push_str(&format
!("{}: ", lifetime
));
204 for (i
, lifetime
) in bounds
.iter().enumerate() {
206 clause
.push_str(" + ");
209 clause
.push_str(&lifetime
.to_string());
212 &clean
::WherePredicate
::EqPredicate { ref lhs, ref rhs }
=> {
214 clause
.push_str(&format
!("{:#} == {:#}", lhs
, rhs
));
216 clause
.push_str(&format
!("{} == {}", lhs
, rhs
));
221 if i
< gens
.where_predicates
.len() - 1 || end_newline
{
227 // add a space so stripping <br> tags and breaking spaces still renders properly
231 clause
.push_str(" ");
236 clause
.push_str("</span>");
237 let padding
= " ".repeat(indent
+ 4);
238 clause
= clause
.replace("<br>", &format
!("<br>{}", padding
));
239 clause
.insert_str(0, &" ".repeat(indent
.saturating_sub(1)));
241 clause
.insert_str(0, "<br>");
244 write
!(f
, "{}", clause
)
248 impl fmt
::Display
for clean
::Lifetime
{
249 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
250 f
.write_str(self.get_ref())?
;
255 impl fmt
::Display
for clean
::PolyTrait
{
256 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
257 if !self.generic_params
.is_empty() {
259 write
!(f
, "for<{:#}> ", CommaSep(&self.generic_params
))?
;
261 write
!(f
, "for<{}> ", CommaSep(&self.generic_params
))?
;
265 write
!(f
, "{:#}", self.trait_
)
267 write
!(f
, "{}", self.trait_
)
272 impl fmt
::Display
for clean
::GenericBound
{
273 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
275 clean
::GenericBound
::Outlives(ref lt
) => {
278 clean
::GenericBound
::TraitBound(ref ty
, modifier
) => {
279 let modifier_str
= match modifier
{
280 hir
::TraitBoundModifier
::None
=> "",
281 hir
::TraitBoundModifier
::Maybe
=> "?",
284 write
!(f
, "{}{:#}", modifier_str
, *ty
)
286 write
!(f
, "{}{}", modifier_str
, *ty
)
293 impl fmt
::Display
for clean
::GenericArgs
{
294 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
296 clean
::GenericArgs
::AngleBracketed
{
297 ref lifetimes
, ref types
, ref bindings
299 if !lifetimes
.is_empty() || !types
.is_empty() || !bindings
.is_empty() {
303 f
.write_str("<")?
;
305 let mut comma
= false;
306 for lifetime
in lifetimes
{
311 write
!(f
, "{}", *lifetime
)?
;
319 write
!(f
, "{:#}", *ty
)?
;
321 write
!(f
, "{}", *ty
)?
;
324 for binding
in bindings
{
330 write
!(f
, "{:#}", *binding
)?
;
332 write
!(f
, "{}", *binding
)?
;
338 f
.write_str(">")?
;
342 clean
::GenericArgs
::Parenthesized { ref inputs, ref output }
=> {
344 let mut comma
= false;
351 write
!(f
, "{:#}", *ty
)?
;
353 write
!(f
, "{}", *ty
)?
;
357 if let Some(ref ty
) = *output
{
359 write
!(f
, " -> {:#}", ty
)?
;
361 write
!(f
, " -> {}", ty
)?
;
370 impl fmt
::Display
for clean
::PathSegment
{
371 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
372 f
.write_str(&self.name
)?
;
374 write
!(f
, "{:#}", self.args
)
376 write
!(f
, "{}", self.args
)
381 impl fmt
::Display
for clean
::Path
{
382 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
387 for (i
, seg
) in self.segments
.iter().enumerate() {
392 write
!(f
, "{:#}", seg
)?
;
394 write
!(f
, "{}", seg
)?
;
401 pub fn href(did
: DefId
) -> Option
<(String
, ItemType
, Vec
<String
>)> {
403 if !did
.is_local() && !cache
.access_levels
.is_doc_reachable(did
) {
407 let loc
= CURRENT_LOCATION_KEY
.with(|l
| l
.borrow().clone());
408 let (fqp
, shortty
, mut url
) = match cache
.paths
.get(&did
) {
409 Some(&(ref fqp
, shortty
)) => {
410 (fqp
, shortty
, "../".repeat(loc
.len()))
413 let &(ref fqp
, shortty
) = cache
.external_paths
.get(&did
)?
;
414 (fqp
, shortty
, match cache
.extern_locations
[&did
.krate
] {
415 (.., render
::Remote(ref s
)) => s
.to_string(),
416 (.., render
::Local
) => "../".repeat(loc
.len()),
417 (.., render
::Unknown
) => return None
,
421 for component
in &fqp
[..fqp
.len() - 1] {
422 url
.push_str(component
);
426 ItemType
::Module
=> {
427 url
.push_str(fqp
.last().unwrap());
428 url
.push_str("/index.html");
431 url
.push_str(shortty
.css_class());
433 url
.push_str(fqp
.last().unwrap());
434 url
.push_str(".html");
437 Some((url
, shortty
, fqp
.to_vec()))
440 /// Used when rendering a `ResolvedPath` structure. This invokes the `path`
441 /// rendering function with the necessary arguments for linking to a local path.
442 fn resolved_path(w
: &mut fmt
::Formatter
, did
: DefId
, path
: &clean
::Path
,
443 print_all
: bool
, use_absolute
: bool
) -> fmt
::Result
{
444 let last
= path
.segments
.last().unwrap();
447 for seg
in &path
.segments
[..path
.segments
.len() - 1] {
448 write
!(w
, "{}::", seg
.name
)?
;
452 write
!(w
, "{:#}{:#}", HRef
::new(did
, &last
.name
), last
.args
)?
;
454 let path
= if use_absolute
{
456 Some((_
, _
, fqp
)) => {
458 fqp
[..fqp
.len() - 1].join("::"),
459 HRef
::new(did
, fqp
.last().unwrap()))
461 None
=> HRef
::new(did
, &last
.name
).to_string(),
464 HRef
::new(did
, &last
.name
).to_string()
466 write
!(w
, "{}{}", path
, last
.args
)?
;
471 fn primitive_link(f
: &mut fmt
::Formatter
,
472 prim
: clean
::PrimitiveType
,
473 name
: &str) -> fmt
::Result
{
475 let mut needs_termination
= false;
477 match m
.primitive_locations
.get(&prim
) {
478 Some(&def_id
) if def_id
.is_local() => {
479 let len
= CURRENT_LOCATION_KEY
.with(|s
| s
.borrow().len());
480 let len
= if len
== 0 {0}
else {len - 1}
;
481 write
!(f
, "<a class=\"primitive\" href=\"{}primitive.{}.html\">",
484 needs_termination
= true;
487 let loc
= match m
.extern_locations
[&def_id
.krate
] {
488 (ref cname
, _
, render
::Remote(ref s
)) => {
489 Some((cname
, s
.to_string()))
491 (ref cname
, _
, render
::Local
) => {
492 let len
= CURRENT_LOCATION_KEY
.with(|s
| s
.borrow().len());
493 Some((cname
, "../".repeat(len
)))
495 (.., render
::Unknown
) => None
,
497 if let Some((cname
, root
)) = loc
{
498 write
!(f
, "<a class=\"primitive\" href=\"{}{}/primitive.{}.html\">",
502 needs_termination
= true;
508 write
!(f
, "{}", name
)?
;
509 if needs_termination
{
515 /// Helper to render type parameters
516 fn tybounds(w
: &mut fmt
::Formatter
,
517 typarams
: &Option
<Vec
<clean
::GenericBound
>>) -> fmt
::Result
{
519 Some(ref params
) => {
520 for param
in params
{
522 fmt
::Display
::fmt(param
, w
)?
;
531 pub fn new(did
: DefId
, text
: &'a
str) -> HRef
<'a
> {
532 HRef { did: did, text: text }
536 impl<'a
> fmt
::Display
for HRef
<'a
> {
537 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
538 match href(self.did
) {
539 Some((url
, shortty
, fqp
)) => if !f
.alternate() {
540 write
!(f
, "<a class=\"{}\" href=\"{}\" title=\"{} {}\">{}</a>",
541 shortty
, url
, shortty
, fqp
.join("::"), self.text
)
543 write
!(f
, "{}", self.text
)
545 _
=> write
!(f
, "{}", self.text
),
550 fn fmt_type(t
: &clean
::Type
, f
: &mut fmt
::Formatter
, use_absolute
: bool
) -> fmt
::Result
{
552 clean
::Generic(ref name
) => {
555 clean
::ResolvedPath{ did, ref typarams, ref path, is_generic }
=> {
556 if typarams
.is_some() {
557 f
.write_str("dyn ")?
;
559 // Paths like T::Output and Self::Output should be rendered with all segments
560 resolved_path(f
, did
, path
, is_generic
, use_absolute
)?
;
561 tybounds(f
, typarams
)
563 clean
::Infer
=> write
!(f
, "_"),
564 clean
::Primitive(prim
) => primitive_link(f
, prim
, prim
.as_str()),
565 clean
::BareFunction(ref decl
) => {
567 write
!(f
, "{}{:#}fn{:#}{:#}",
568 UnsafetySpace(decl
.unsafety
),
570 CommaSep(&decl
.generic_params
),
573 write
!(f
, "{}{}", UnsafetySpace(decl
.unsafety
), AbiSpace(decl
.abi
))?
;
574 primitive_link(f
, PrimitiveType
::Fn
, "fn")?
;
575 write
!(f
, "{}{}", CommaSep(&decl
.generic_params
), decl
.decl
)
578 clean
::Tuple(ref typs
) => {
580 &[] => primitive_link(f
, PrimitiveType
::Unit
, "()"),
582 primitive_link(f
, PrimitiveType
::Tuple
, "(")?
;
583 //carry f.alternate() into this display w/o branching manually
584 fmt
::Display
::fmt(one
, f
)?
;
585 primitive_link(f
, PrimitiveType
::Tuple
, ",)")
588 primitive_link(f
, PrimitiveType
::Tuple
, "(")?
;
589 fmt
::Display
::fmt(&CommaSep(many
), f
)?
;
590 primitive_link(f
, PrimitiveType
::Tuple
, ")")
594 clean
::Slice(ref t
) => {
595 primitive_link(f
, PrimitiveType
::Slice
, "[")?
;
596 fmt
::Display
::fmt(t
, f
)?
;
597 primitive_link(f
, PrimitiveType
::Slice
, "]")
599 clean
::Array(ref t
, ref n
) => {
600 primitive_link(f
, PrimitiveType
::Array
, "[")?
;
601 fmt
::Display
::fmt(t
, f
)?
;
602 primitive_link(f
, PrimitiveType
::Array
, &format
!("; {}]", n
))
604 clean
::Never
=> primitive_link(f
, PrimitiveType
::Never
, "!"),
605 clean
::RawPointer(m
, ref t
) => {
607 clean
::Generic(_
) | clean
::ResolvedPath {is_generic: true, ..}
=> {
609 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
610 &format
!("*{}{:#}", RawMutableSpace(m
), t
))
612 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
613 &format
!("*{}{}", RawMutableSpace(m
), t
))
617 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
618 &format
!("*{}", RawMutableSpace(m
)))?
;
619 fmt
::Display
::fmt(t
, f
)
623 clean
::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty}
=> {
625 Some(ref l
) => format
!("{} ", *l
),
628 let m
= MutableSpace(mutability
);
629 let amp
= if f
.alternate() {
635 clean
::Slice(ref bt
) => { // BorrowedRef{ ... Slice(T) } is
&[T
]
637 clean
::Generic(_
) => {
639 primitive_link(f
, PrimitiveType
::Slice
,
640 &format
!("{}{}{}[{:#}]", amp
, lt
, m
, **bt
))
642 primitive_link(f
, PrimitiveType
::Slice
,
643 &format
!("{}{}{}[{}]", amp
, lt
, m
, **bt
))
647 primitive_link(f
, PrimitiveType
::Slice
,
648 &format
!("{}{}{}[", amp
, lt
, m
))?
;
650 write
!(f
, "{:#}", **bt
)?
;
652 write
!(f
, "{}", **bt
)?
;
654 primitive_link(f
, PrimitiveType
::Slice
, "]")
658 clean
::ResolvedPath { typarams: Some(ref v), .. }
if !v
.is_empty() => {
659 write
!(f
, "{}{}{}(", amp
, lt
, m
)?
;
660 fmt_type(&ty
, f
, use_absolute
)?
;
663 clean
::Generic(..) => {
664 primitive_link(f
, PrimitiveType
::Reference
,
665 &format
!("{}{}{}", amp
, lt
, m
))?
;
666 fmt_type(&ty
, f
, use_absolute
)
669 write
!(f
, "{}{}{}", amp
, lt
, m
)?
;
670 fmt_type(&ty
, f
, use_absolute
)
674 clean
::ImplTrait(ref bounds
) => {
675 write
!(f
, "impl {}", GenericBounds(bounds
))
677 clean
::QPath { ref name, ref self_type, ref trait_ }
=> {
678 let should_show_cast
= match *trait_
{
679 box clean
::ResolvedPath { ref path, .. }
=> {
680 !path
.segments
.is_empty() && !self_type
.is_self_type()
685 if should_show_cast
{
686 write
!(f
, "<{:#} as {:#}>::", self_type
, trait_
)?
688 write
!(f
, "{:#}::", self_type
)?
691 if should_show_cast
{
692 write
!(f
, "<{} as {}>::", self_type
, trait_
)?
694 write
!(f
, "{}::", self_type
)?
698 // It's pretty unsightly to look at `<A as B>::C` in output, and
699 // we've got hyperlinking on our side, so try to avoid longer
700 // notation as much as possible by making `C` a hyperlink to trait
701 // `B` to disambiguate.
703 // FIXME: this is still a lossy conversion and there should probably
704 // be a better way of representing this in general? Most of
705 // the ugliness comes from inlining across crates where
706 // everything comes in as a fully resolved QPath (hard to
708 box clean
::ResolvedPath { did, ref typarams, .. }
=> {
710 Some((ref url
, _
, ref path
)) if !f
.alternate() => {
712 "<a class=\"type\" href=\"{url}#{shortty}.{name}\" \
713 title=\"type {path}::{name}\">{name}</a>",
715 shortty
= ItemType
::AssociatedType
,
717 path
= path
.join("::"))?
;
719 _
=> write
!(f
, "{}", name
)?
,
722 // FIXME: `typarams` are not rendered, and this seems bad?
727 write
!(f
, "{}", name
)
731 clean
::Unique(..) => {
732 panic
!("should have been cleaned")
737 impl fmt
::Display
for clean
::Type
{
738 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
739 fmt_type(self, f
, false)
743 fn fmt_impl(i
: &clean
::Impl
,
744 f
: &mut fmt
::Formatter
,
746 use_absolute
: bool
) -> fmt
::Result
{
748 write
!(f
, "impl{:#} ", i
.generics
)?
;
750 write
!(f
, "impl{} ", i
.generics
)?
;
753 if let Some(ref ty
) = i
.trait_
{
754 if i
.polarity
== Some(clean
::ImplPolarity
::Negative
) {
759 fmt
::Display
::fmt(ty
, f
)?
;
762 clean
::ResolvedPath { typarams: None, ref path, is_generic: false, .. }
=> {
763 let last
= path
.segments
.last().unwrap();
764 fmt
::Display
::fmt(&last
.name
, f
)?
;
765 fmt
::Display
::fmt(&last
.args
, f
)?
;
773 if let Some(ref ty
) = i
.blanket_impl
{
774 fmt_type(ty
, f
, use_absolute
)?
;
776 fmt_type(&i
.for_
, f
, use_absolute
)?
;
779 fmt
::Display
::fmt(&WhereClause { gens: &i.generics, indent: 0, end_newline: true }
, f
)?
;
783 impl fmt
::Display
for clean
::Impl
{
784 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
785 fmt_impl(self, f
, true, false)
789 // The difference from above is that trait is not hyperlinked.
790 pub fn fmt_impl_for_trait_page(i
: &clean
::Impl
,
791 f
: &mut fmt
::Formatter
,
792 use_absolute
: bool
) -> fmt
::Result
{
793 fmt_impl(i
, f
, false, use_absolute
)
796 impl fmt
::Display
for clean
::Arguments
{
797 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
798 for (i
, input
) in self.values
.iter().enumerate() {
799 if !input
.name
.is_empty() {
800 write
!(f
, "{}: ", input
.name
)?
;
803 write
!(f
, "{:#}", input
.type_
)?
;
805 write
!(f
, "{}", input
.type_
)?
;
807 if i
+ 1 < self.values
.len() { write!(f, ", ")?; }
813 impl fmt
::Display
for clean
::FunctionRetTy
{
814 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
816 clean
::Return(clean
::Tuple(ref tys
)) if tys
.is_empty() => Ok(()),
817 clean
::Return(ref ty
) if f
.alternate() => write
!(f
, " -> {:#}", ty
),
818 clean
::Return(ref ty
) => write
!(f
, " -> {}", ty
),
819 clean
::DefaultReturn
=> Ok(()),
824 impl fmt
::Display
for clean
::FnDecl
{
825 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
828 write
!(f
, "({args:#}, ...){arrow:#}", args
= self.inputs
, arrow
= self.output
)
830 write
!(f
, "({args}, ...){arrow}", args
= self.inputs
, arrow
= self.output
)
834 write
!(f
, "({args:#}){arrow:#}", args
= self.inputs
, arrow
= self.output
)
836 write
!(f
, "({args}){arrow}", args
= self.inputs
, arrow
= self.output
)
842 impl<'a
> fmt
::Display
for Method
<'a
> {
843 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
844 let &Method { decl, name_len, indent }
= self;
845 let amp
= if f
.alternate() { "&" }
else { "&" }
;
846 let mut args
= String
::new();
847 let mut args_plain
= String
::new();
848 for (i
, input
) in decl
.inputs
.values
.iter().enumerate() {
850 args
.push_str("<br>");
853 if let Some(selfty
) = input
.to_self() {
855 clean
::SelfValue
=> {
856 args
.push_str("self");
857 args_plain
.push_str("self");
859 clean
::SelfBorrowed(Some(ref lt
), mtbl
) => {
860 args
.push_str(&format
!("{}{} {}self", amp
, *lt
, MutableSpace(mtbl
)));
861 args_plain
.push_str(&format
!("&{} {}self", *lt
, MutableSpace(mtbl
)));
863 clean
::SelfBorrowed(None
, mtbl
) => {
864 args
.push_str(&format
!("{}{}self", amp
, MutableSpace(mtbl
)));
865 args_plain
.push_str(&format
!("&{}self", MutableSpace(mtbl
)));
867 clean
::SelfExplicit(ref typ
) => {
869 args
.push_str(&format
!("self: {:#}", *typ
));
871 args
.push_str(&format
!("self: {}", *typ
));
873 args_plain
.push_str(&format
!("self: {:#}", *typ
));
878 args
.push_str(" <br>");
879 args_plain
.push_str(" ");
881 if !input
.name
.is_empty() {
882 args
.push_str(&format
!("{}: ", input
.name
));
883 args_plain
.push_str(&format
!("{}: ", input
.name
));
887 args
.push_str(&format
!("{:#}", input
.type_
));
889 args
.push_str(&input
.type_
.to_string());
891 args_plain
.push_str(&format
!("{:#}", input
.type_
));
893 if i
+ 1 < decl
.inputs
.values
.len() {
895 args_plain
.push('
,'
);
900 args
.push_str(",<br> ...");
901 args_plain
.push_str(", ...");
904 let arrow_plain
= format
!("{:#}", decl
.output
);
905 let arrow
= if f
.alternate() {
906 format
!("{:#}", decl
.output
)
908 decl
.output
.to_string()
911 let pad
= " ".repeat(name_len
);
912 let plain
= format
!("{pad}({args}){arrow}",
915 arrow
= arrow_plain
);
917 let output
= if plain
.len() > 80 {
918 let full_pad
= format
!("<br>{}", " ".repeat(indent
+ 4));
919 let close_pad
= format
!("<br>{}", " ".repeat(indent
));
920 format
!("({args}{close}){arrow}",
921 args
= args
.replace("<br>", &full_pad
),
925 format
!("({args}){arrow}", args
= args
.replace("<br>", ""), arrow
= arrow
)
929 write
!(f
, "{}", output
.replace("<br>", "\n"))
931 write
!(f
, "{}", output
)
936 impl<'a
> fmt
::Display
for VisSpace
<'a
> {
937 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
939 Some(clean
::Public
) => f
.write_str("pub "),
940 Some(clean
::Inherited
) | None
=> Ok(()),
941 Some(clean
::Visibility
::Crate
) => write
!(f
, "pub(crate) "),
942 Some(clean
::Visibility
::Restricted(did
, ref path
)) => {
943 f
.write_str("pub(")?
;
944 if path
.segments
.len() != 1
945 || (path
.segments
[0].name
!= "self" && path
.segments
[0].name
!= "super")
949 resolved_path(f
, did
, path
, true, false)?
;
956 impl fmt
::Display
for UnsafetySpace
{
957 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
959 hir
::Unsafety
::Unsafe
=> write
!(f
, "unsafe "),
960 hir
::Unsafety
::Normal
=> Ok(())
965 impl fmt
::Display
for ConstnessSpace
{
966 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
968 hir
::Constness
::Const
=> write
!(f
, "const "),
969 hir
::Constness
::NotConst
=> Ok(())
974 impl fmt
::Display
for AsyncSpace
{
975 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
977 hir
::IsAsync
::Async
=> write
!(f
, "async "),
978 hir
::IsAsync
::NotAsync
=> Ok(()),
983 impl fmt
::Display
for clean
::Import
{
984 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
986 clean
::Import
::Simple(ref name
, ref src
) => {
987 if *name
== src
.path
.last_name() {
988 write
!(f
, "use {};", *src
)
990 write
!(f
, "use {} as {};", *src
, *name
)
993 clean
::Import
::Glob(ref src
) => {
994 if src
.path
.segments
.is_empty() {
997 write
!(f
, "use {}::*;", *src
)
1004 impl fmt
::Display
for clean
::ImportSource
{
1005 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1007 Some(did
) => resolved_path(f
, did
, &self.path
, true, false),
1009 for (i
, seg
) in self.path
.segments
.iter().enumerate() {
1013 write
!(f
, "{}", seg
.name
)?
;
1021 impl fmt
::Display
for clean
::TypeBinding
{
1022 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1024 write
!(f
, "{} = {:#}", self.name
, self.ty
)
1026 write
!(f
, "{} = {}", self.name
, self.ty
)
1031 impl fmt
::Display
for MutableSpace
{
1032 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1034 MutableSpace(clean
::Immutable
) => Ok(()),
1035 MutableSpace(clean
::Mutable
) => write
!(f
, "mut "),
1040 impl fmt
::Display
for RawMutableSpace
{
1041 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1043 RawMutableSpace(clean
::Immutable
) => write
!(f
, "const "),
1044 RawMutableSpace(clean
::Mutable
) => write
!(f
, "mut "),
1049 impl fmt
::Display
for AbiSpace
{
1050 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1051 let quot
= if f
.alternate() { "\"" }
else { """ }
;
1053 Abi
::Rust
=> Ok(()),
1054 abi
=> write
!(f
, "extern {0}{1}{0} ", quot
, abi
.name()),