about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2021-04-10 14:22:06 -0700
committerMichael Howell <michael@notriddle.com>2021-04-10 14:22:06 -0700
commit2dfd0bfe1087fef83f26b52b32c8b54fb621b6b9 (patch)
tree8261d6dfe783f1fb810adc334d5f7428eec21e94
parent72c63de2ccf8445bfe27dcfb4f712bc771da1b15 (diff)
downloadrust-2dfd0bfe1087fef83f26b52b32c8b54fb621b6b9.tar.gz
rust-2dfd0bfe1087fef83f26b52b32c8b54fb621b6b9.zip
rustdoc: clean up and test macro visibility print
This fixes the overly-complex invariant mentioned in
<https://github.com/rust-lang/rust/pull/83237#issuecomment-815346570>,
where the macro source can't have any links in it only because the
cache hasn't been populated yet.
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/librustdoc/html/format.rs48
-rw-r--r--src/test/rustdoc/decl_macro.rs17
3 files changed, 57 insertions, 12 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 217e899001e..7d33cf21013 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2287,14 +2287,14 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
             if matchers.len() <= 1 {
                 format!(
                     "{}macro {}{} {{\n    ...\n}}",
-                    vis.print_with_space(cx.tcx, def_id, &cx.cache),
+                    vis.to_src_with_space(cx.tcx, def_id),
                     name,
                     matchers.iter().map(|span| span.to_src(cx)).collect::<String>(),
                 )
             } else {
                 format!(
                     "{}macro {} {{\n{}}}",
-                    vis.print_with_space(cx.tcx, def_id, &cx.cache),
+                    vis.to_src_with_space(cx.tcx, def_id),
                     name,
                     matchers
                         .iter()
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index a004ee5054e..41f531e77e5 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1186,8 +1186,6 @@ impl clean::Visibility {
         item_did: DefId,
         cache: &'a Cache,
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
-        use rustc_span::symbol::kw;
-
         let to_print = match self {
             clean::Public => "pub ".to_owned(),
             clean::Inherited => String::new(),
@@ -1212,18 +1210,11 @@ impl clean::Visibility {
                 } else {
                     let path = tcx.def_path(vis_did);
                     debug!("path={:?}", path);
-                    let first_name =
-                        path.data[0].data.get_opt_name().expect("modules are always named");
                     // modified from `resolved_path()` to work with `DefPathData`
                     let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
                     let anchor = anchor(vis_did, &last_name.as_str(), cache).to_string();
 
-                    let mut s = "pub(".to_owned();
-                    if path.data.len() != 1
-                        || (first_name != kw::SelfLower && first_name != kw::Super)
-                    {
-                        s.push_str("in ");
-                    }
+                    let mut s = "pub(in ".to_owned();
                     for seg in &path.data[..path.data.len() - 1] {
                         s.push_str(&format!("{}::", seg.data.get_opt_name().unwrap()));
                     }
@@ -1234,6 +1225,43 @@ impl clean::Visibility {
         };
         display_fn(move |f| f.write_str(&to_print))
     }
+
+    /// This function is the same as print_with_space, except that it renders no links.
+    /// It's used for macros' rendered source view, which is syntax highlighted and cannot have
+    /// any HTML in it.
+    crate fn to_src_with_space<'a, 'tcx: 'a>(
+        self,
+        tcx: TyCtxt<'tcx>,
+        item_did: DefId,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
+        let to_print = match self {
+            clean::Public => "pub ".to_owned(),
+            clean::Inherited => String::new(),
+            clean::Visibility::Restricted(vis_did) => {
+                // FIXME(camelid): This may not work correctly if `item_did` is a module.
+                //                 However, rustdoc currently never displays a module's
+                //                 visibility, so it shouldn't matter.
+                let parent_module = find_nearest_parent_module(tcx, item_did);
+
+                if vis_did.index == CRATE_DEF_INDEX {
+                    "pub(crate) ".to_owned()
+                } else if parent_module == Some(vis_did) {
+                    // `pub(in foo)` where `foo` is the parent module
+                    // is the same as no visibility modifier
+                    String::new()
+                } else if parent_module
+                    .map(|parent| find_nearest_parent_module(tcx, parent))
+                    .flatten()
+                    == Some(vis_did)
+                {
+                    "pub(super) ".to_owned()
+                } else {
+                    format!("pub(in {}) ", tcx.def_path_str(vis_did))
+                }
+            }
+        };
+        display_fn(move |f| f.write_str(&to_print))
+    }
 }
 
 crate trait PrintWithSpace {
diff --git a/src/test/rustdoc/decl_macro.rs b/src/test/rustdoc/decl_macro.rs
index e48a56f906c..ede3f455a20 100644
--- a/src/test/rustdoc/decl_macro.rs
+++ b/src/test/rustdoc/decl_macro.rs
@@ -1,3 +1,5 @@
+// compile-flags: --document-private-items
+
 #![feature(decl_macro)]
 
 // @has decl_macro/macro.my_macro.html //pre 'pub macro my_macro() {'
@@ -37,3 +39,18 @@ pub macro my_macro_multi {
 pub macro by_example_single {
     ($foo:expr) => {}
 }
+
+mod a {
+    mod b {
+        // @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo:expr) {'
+        pub(in super) macro by_example_vis {
+            ($foo:expr) => {}
+        }
+        mod c {
+            // @has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {'
+            pub(in a) macro by_example_vis_named {
+                ($foo:expr) => {}
+            }
+        }
+    }
+}