|
7 | 7 | //! some of them support an alternate format that emits text, but that should
|
8 | 8 | //! not be used external to this module.
|
9 | 9 |
|
10 |
| -use std::borrow::Cow; |
11 | 10 | use std::cmp::Ordering;
|
12 | 11 | use std::fmt::{self, Display, Write};
|
13 | 12 | use std::iter::{self, once};
|
@@ -37,115 +36,6 @@ use crate::html::render::Context;
|
37 | 36 | use crate::joined::Joined as _;
|
38 | 37 | use crate::passes::collect_intra_doc_links::UrlFragment;
|
39 | 38 |
|
40 |
| -pub(crate) trait Print { |
41 |
| - fn print(self, buffer: &mut Buffer); |
42 |
| -} |
43 |
| - |
44 |
| -impl<F> Print for F |
45 |
| -where |
46 |
| - F: FnOnce(&mut Buffer), |
47 |
| -{ |
48 |
| - fn print(self, buffer: &mut Buffer) { |
49 |
| - (self)(buffer) |
50 |
| - } |
51 |
| -} |
52 |
| - |
53 |
| -impl Print for String { |
54 |
| - fn print(self, buffer: &mut Buffer) { |
55 |
| - buffer.write_str(&self); |
56 |
| - } |
57 |
| -} |
58 |
| - |
59 |
| -impl Print for &'_ str { |
60 |
| - fn print(self, buffer: &mut Buffer) { |
61 |
| - buffer.write_str(self); |
62 |
| - } |
63 |
| -} |
64 |
| - |
65 |
| -#[derive(Debug, Clone)] |
66 |
| -pub(crate) struct Buffer { |
67 |
| - for_html: bool, |
68 |
| - buffer: String, |
69 |
| -} |
70 |
| - |
71 |
| -impl core::fmt::Write for Buffer { |
72 |
| - #[inline] |
73 |
| - fn write_str(&mut self, s: &str) -> fmt::Result { |
74 |
| - self.buffer.write_str(s) |
75 |
| - } |
76 |
| - |
77 |
| - #[inline] |
78 |
| - fn write_char(&mut self, c: char) -> fmt::Result { |
79 |
| - self.buffer.write_char(c) |
80 |
| - } |
81 |
| - |
82 |
| - #[inline] |
83 |
| - fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { |
84 |
| - self.buffer.write_fmt(args) |
85 |
| - } |
86 |
| -} |
87 |
| - |
88 |
| -impl Buffer { |
89 |
| - pub(crate) fn empty_from(v: &Buffer) -> Buffer { |
90 |
| - Buffer { for_html: v.for_html, buffer: String::new() } |
91 |
| - } |
92 |
| - |
93 |
| - pub(crate) fn html() -> Buffer { |
94 |
| - Buffer { for_html: true, buffer: String::new() } |
95 |
| - } |
96 |
| - |
97 |
| - pub(crate) fn new() -> Buffer { |
98 |
| - Buffer { for_html: false, buffer: String::new() } |
99 |
| - } |
100 |
| - |
101 |
| - pub(crate) fn is_empty(&self) -> bool { |
102 |
| - self.buffer.is_empty() |
103 |
| - } |
104 |
| - |
105 |
| - pub(crate) fn into_inner(self) -> String { |
106 |
| - self.buffer |
107 |
| - } |
108 |
| - |
109 |
| - pub(crate) fn push(&mut self, c: char) { |
110 |
| - self.buffer.push(c); |
111 |
| - } |
112 |
| - |
113 |
| - pub(crate) fn push_str(&mut self, s: &str) { |
114 |
| - self.buffer.push_str(s); |
115 |
| - } |
116 |
| - |
117 |
| - pub(crate) fn push_buffer(&mut self, other: Buffer) { |
118 |
| - self.buffer.push_str(&other.buffer); |
119 |
| - } |
120 |
| - |
121 |
| - // Intended for consumption by write! and writeln! (std::fmt) but without |
122 |
| - // the fmt::Result return type imposed by fmt::Write (and avoiding the trait |
123 |
| - // import). |
124 |
| - pub(crate) fn write_str(&mut self, s: &str) { |
125 |
| - self.buffer.push_str(s); |
126 |
| - } |
127 |
| - |
128 |
| - // Intended for consumption by write! and writeln! (std::fmt) but without |
129 |
| - // the fmt::Result return type imposed by fmt::Write (and avoiding the trait |
130 |
| - // import). |
131 |
| - pub(crate) fn write_fmt(&mut self, v: fmt::Arguments<'_>) { |
132 |
| - self.buffer.write_fmt(v).unwrap(); |
133 |
| - } |
134 |
| - |
135 |
| - pub(crate) fn to_display<T: Print>(mut self, t: T) -> String { |
136 |
| - t.print(&mut self); |
137 |
| - self.into_inner() |
138 |
| - } |
139 |
| - |
140 |
| - pub(crate) fn reserve(&mut self, additional: usize) { |
141 |
| - self.buffer.reserve(additional) |
142 |
| - } |
143 |
| - |
144 |
| - pub(crate) fn len(&self) -> usize { |
145 |
| - self.buffer.len() |
146 |
| - } |
147 |
| -} |
148 |
| - |
149 | 39 | pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
|
150 | 40 | bounds: &'a [clean::GenericBound],
|
151 | 41 | cx: &'a Context<'tcx>,
|
@@ -772,27 +662,29 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont
|
772 | 662 | else {
|
773 | 663 | return String::new();
|
774 | 664 | };
|
775 |
| - let mut buf = Buffer::new(); |
776 | 665 | let fqp = if *shortty == ItemType::Primitive {
|
777 | 666 | // primitives are documented in a crate, but not actually part of it
|
778 | 667 | &fqp[fqp.len() - 1..]
|
779 | 668 | } else {
|
780 | 669 | fqp
|
781 | 670 | };
|
782 |
| - if let &Some(UrlFragment::Item(id)) = fragment { |
783 |
| - write!(buf, "{} ", cx.tcx().def_descr(id)); |
784 |
| - for component in fqp { |
785 |
| - write!(buf, "{component}::"); |
786 |
| - } |
787 |
| - write!(buf, "{}", cx.tcx().item_name(id)); |
788 |
| - } else if !fqp.is_empty() { |
789 |
| - let mut fqp_it = fqp.iter(); |
790 |
| - write!(buf, "{shortty} {}", fqp_it.next().unwrap()); |
791 |
| - for component in fqp_it { |
792 |
| - write!(buf, "::{component}"); |
| 671 | + fmt::from_fn(|f| { |
| 672 | + if let &Some(UrlFragment::Item(id)) = fragment { |
| 673 | + write!(f, "{} ", cx.tcx().def_descr(id))?; |
| 674 | + for component in fqp { |
| 675 | + write!(f, "{component}::")?; |
| 676 | + } |
| 677 | + write!(f, "{}", cx.tcx().item_name(id))?; |
| 678 | + } else if !fqp.is_empty() { |
| 679 | + let mut fqp_it = fqp.iter(); |
| 680 | + write!(f, "{shortty} {}", fqp_it.next().unwrap())?; |
| 681 | + for component in fqp_it { |
| 682 | + write!(f, "::{component}")?; |
| 683 | + } |
793 | 684 | }
|
794 |
| - } |
795 |
| - buf.into_inner() |
| 685 | + Ok(()) |
| 686 | + }) |
| 687 | + .to_string() |
796 | 688 | }
|
797 | 689 |
|
798 | 690 | /// Used to render a [`clean::Path`].
|
@@ -954,7 +846,7 @@ pub(crate) fn anchor<'a: 'cx, 'cx>(
|
954 | 846 | text = EscapeBodyText(text.as_str()),
|
955 | 847 | )
|
956 | 848 | } else {
|
957 |
| - f.write_str(text.as_str()) |
| 849 | + write!(f, "{text}") |
958 | 850 | }
|
959 | 851 | })
|
960 | 852 | }
|
@@ -1533,53 +1425,51 @@ impl clean::FnDecl {
|
1533 | 1425 | }
|
1534 | 1426 |
|
1535 | 1427 | pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
|
1536 |
| - item: &clean::Item, |
| 1428 | + item: &'a clean::Item, |
1537 | 1429 | cx: &'a Context<'tcx>,
|
1538 | 1430 | ) -> impl Display + 'a + Captures<'tcx> {
|
1539 |
| - use std::fmt::Write as _; |
1540 |
| - let vis: Cow<'static, str> = match item.visibility(cx.tcx()) { |
1541 |
| - None => "".into(), |
1542 |
| - Some(ty::Visibility::Public) => "pub ".into(), |
1543 |
| - Some(ty::Visibility::Restricted(vis_did)) => { |
1544 |
| - // FIXME(camelid): This may not work correctly if `item_did` is a module. |
1545 |
| - // However, rustdoc currently never displays a module's |
1546 |
| - // visibility, so it shouldn't matter. |
1547 |
| - let parent_module = find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id()); |
1548 |
| - |
1549 |
| - if vis_did.is_crate_root() { |
1550 |
| - "pub(crate) ".into() |
1551 |
| - } else if parent_module == Some(vis_did) { |
1552 |
| - // `pub(in foo)` where `foo` is the parent module |
1553 |
| - // is the same as no visibility modifier |
1554 |
| - "".into() |
1555 |
| - } else if parent_module.and_then(|parent| find_nearest_parent_module(cx.tcx(), parent)) |
1556 |
| - == Some(vis_did) |
1557 |
| - { |
1558 |
| - "pub(super) ".into() |
1559 |
| - } else { |
1560 |
| - let path = cx.tcx().def_path(vis_did); |
1561 |
| - debug!("path={path:?}"); |
1562 |
| - // modified from `resolved_path()` to work with `DefPathData` |
1563 |
| - let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); |
1564 |
| - let anchor = anchor(vis_did, last_name, cx); |
1565 |
| - |
1566 |
| - let mut s = "pub(in ".to_owned(); |
1567 |
| - for seg in &path.data[..path.data.len() - 1] { |
1568 |
| - let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap()); |
1569 |
| - } |
1570 |
| - let _ = write!(s, "{anchor}) "); |
1571 |
| - s.into() |
1572 |
| - } |
1573 |
| - } |
1574 |
| - }; |
1575 |
| - |
1576 | 1431 | let is_doc_hidden = item.is_doc_hidden();
|
1577 | 1432 | fmt::from_fn(move |f| {
|
1578 | 1433 | if is_doc_hidden {
|
1579 | 1434 | f.write_str("#[doc(hidden)] ")?;
|
1580 | 1435 | }
|
1581 | 1436 |
|
1582 |
| - f.write_str(&vis) |
| 1437 | + match item.visibility(cx.tcx()) { |
| 1438 | + None => Ok(()), |
| 1439 | + Some(ty::Visibility::Public) => f.write_str("pub "), |
| 1440 | + Some(ty::Visibility::Restricted(vis_did)) => { |
| 1441 | + // FIXME(camelid): This may not work correctly if `item_did` is a module. |
| 1442 | + // However, rustdoc currently never displays a module's |
| 1443 | + // visibility, so it shouldn't matter. |
| 1444 | + let parent_module = |
| 1445 | + find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id()); |
| 1446 | + |
| 1447 | + if vis_did.is_crate_root() { |
| 1448 | + f.write_str("pub(crate) ") |
| 1449 | + } else if parent_module == Some(vis_did) { |
| 1450 | + // `pub(in foo)` where `foo` is the parent module |
| 1451 | + // is the same as no visibility modifier |
| 1452 | + Ok(()) |
| 1453 | + } else if parent_module |
| 1454 | + .and_then(|parent| find_nearest_parent_module(cx.tcx(), parent)) |
| 1455 | + == Some(vis_did) |
| 1456 | + { |
| 1457 | + f.write_str("pub(super) ") |
| 1458 | + } else { |
| 1459 | + let path = cx.tcx().def_path(vis_did); |
| 1460 | + debug!("path={path:?}"); |
| 1461 | + // modified from `resolved_path()` to work with `DefPathData` |
| 1462 | + let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); |
| 1463 | + let anchor = anchor(vis_did, last_name, cx); |
| 1464 | + |
| 1465 | + f.write_str("pub(in ")?; |
| 1466 | + for seg in &path.data[..path.data.len() - 1] { |
| 1467 | + write!(f, "{}::", seg.data.get_opt_name().unwrap())?; |
| 1468 | + } |
| 1469 | + write!(f, "{anchor}) ") |
| 1470 | + } |
| 1471 | + } |
| 1472 | + } |
1583 | 1473 | })
|
1584 | 1474 | }
|
1585 | 1475 |
|
|
0 commit comments