|
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