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