]> git.lizzy.rs Git - rust.git/blobdiff - src/librustdoc/html/render/write_shared.rs
Auto merge of #106696 - kylematsuda:early-binder, r=lcnr
[rust.git] / src / librustdoc / html / render / write_shared.rs
index eaf149a43005b63fa249a10be15df1e54db3aec8..ca3e9916487aad060546b9ac358d9f3a7fb20515 100644 (file)
@@ -1,8 +1,9 @@
+use std::cell::RefCell;
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
 use std::path::{Component, Path};
-use std::rc::Rc;
+use std::rc::{Rc, Weak};
 
 use itertools::Itertools;
 use rustc_data_structures::flock;
@@ -184,23 +185,26 @@ fn collect_json(path: &Path, krate: &str) -> io::Result<(Vec<String>, Vec<String
 
     use std::ffi::OsString;
 
-    #[derive(Debug)]
+    #[derive(Debug, Default)]
     struct Hierarchy {
+        parent: Weak<Self>,
         elem: OsString,
-        children: FxHashMap<OsString, Hierarchy>,
-        elems: FxHashSet<OsString>,
+        children: RefCell<FxHashMap<OsString, Rc<Self>>>,
+        elems: RefCell<FxHashSet<OsString>>,
     }
 
     impl Hierarchy {
-        fn new(elem: OsString) -> Hierarchy {
-            Hierarchy { elem, children: FxHashMap::default(), elems: FxHashSet::default() }
+        fn with_parent(elem: OsString, parent: &Rc<Self>) -> Self {
+            Self { elem, parent: Rc::downgrade(parent), ..Self::default() }
         }
 
         fn to_json_string(&self) -> String {
-            let mut subs: Vec<&Hierarchy> = self.children.values().collect();
+            let borrow = self.children.borrow();
+            let mut subs: Vec<_> = borrow.values().collect();
             subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem));
             let mut files = self
                 .elems
+                .borrow()
                 .iter()
                 .map(|s| format!("\"{}\"", s.to_str().expect("invalid osstring conversion")))
                 .collect::<Vec<_>>();
@@ -220,36 +224,52 @@ fn to_json_string(&self) -> String {
                 files = files
             )
         }
-    }
 
-    if cx.include_sources {
-        let mut hierarchy = Hierarchy::new(OsString::new());
-        for source in cx
-            .shared
-            .local_sources
-            .iter()
-            .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok())
-        {
-            let mut h = &mut hierarchy;
-            let mut elems = source
+        fn add_path(self: &Rc<Self>, path: &Path) {
+            let mut h = Rc::clone(&self);
+            let mut elems = path
                 .components()
                 .filter_map(|s| match s {
                     Component::Normal(s) => Some(s.to_owned()),
+                    Component::ParentDir => Some(OsString::from("..")),
                     _ => None,
                 })
                 .peekable();
             loop {
                 let cur_elem = elems.next().expect("empty file path");
+                if cur_elem == ".." {
+                    if let Some(parent) = h.parent.upgrade() {
+                        h = parent;
+                    }
+                    continue;
+                }
                 if elems.peek().is_none() {
-                    h.elems.insert(cur_elem);
+                    h.elems.borrow_mut().insert(cur_elem);
                     break;
                 } else {
-                    let e = cur_elem.clone();
-                    h = h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e));
+                    let entry = Rc::clone(
+                        h.children
+                            .borrow_mut()
+                            .entry(cur_elem.clone())
+                            .or_insert_with(|| Rc::new(Self::with_parent(cur_elem, &h))),
+                    );
+                    h = entry;
                 }
             }
         }
+    }
 
+    if cx.include_sources {
+        let hierarchy = Rc::new(Hierarchy::default());
+        for source in cx
+            .shared
+            .local_sources
+            .iter()
+            .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok())
+        {
+            hierarchy.add_path(source);
+        }
+        let hierarchy = Rc::try_unwrap(hierarchy).unwrap();
         let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
         let make_sources = || {
             let (mut all_sources, _krates) =
@@ -325,7 +345,7 @@ fn to_json_string(&self) -> String {
             };
 
             let content = format!(
-                "<h1 class=\"fqn\">List of all crates</h1><ul class=\"all-items\">{}</ul>",
+                "<h1>List of all crates</h1><ul class=\"all-items\">{}</ul>",
                 krates
                     .iter()
                     .map(|s| {