about summary refs log tree commit diff
path: root/src/librustdoc/passes/collapse_docs.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/passes/collapse_docs.rs')
-rw-r--r--src/librustdoc/passes/collapse_docs.rs72
1 files changed, 63 insertions, 9 deletions
diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs
index 3c63302127c..a2d651d29de 100644
--- a/src/librustdoc/passes/collapse_docs.rs
+++ b/src/librustdoc/passes/collapse_docs.rs
@@ -8,10 +8,28 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use clean::{self, Item};
+use clean::{self, DocFragment, Item};
 use plugins;
 use fold;
 use fold::DocFolder;
+use std::mem::replace;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum DocFragmentKind {
+    Sugared,
+    Raw,
+    Include,
+}
+
+impl DocFragment {
+    fn kind(&self) -> DocFragmentKind {
+        match *self {
+            DocFragment::SugaredDoc(..) => DocFragmentKind::Sugared,
+            DocFragment::RawDoc(..) => DocFragmentKind::Raw,
+            DocFragment::Include(..) => DocFragmentKind::Include,
+        }
+    }
+}
 
 pub fn collapse_docs(krate: clean::Crate) -> plugins::PluginResult {
     Collapser.fold_crate(krate)
@@ -26,15 +44,51 @@ impl fold::DocFolder for Collapser {
     }
 }
 
-impl clean::Attributes {
-    pub fn collapse_doc_comments(&mut self) {
-        let mut doc_string = self.doc_strings.join("\n");
-        if doc_string.is_empty() {
-            self.doc_strings = vec![];
+fn collapse(doc_strings: &mut Vec<DocFragment>) {
+    let mut docs = vec![];
+    let mut last_frag: Option<DocFragment> = None;
+
+    for frag in replace(doc_strings, vec![]) {
+        if let Some(mut curr_frag) = last_frag.take() {
+            let curr_kind = curr_frag.kind();
+            let new_kind = frag.kind();
+
+            if curr_kind == DocFragmentKind::Include || curr_kind != new_kind {
+                match curr_frag {
+                    DocFragment::SugaredDoc(_, _, ref mut doc_string)
+                        | DocFragment::RawDoc(_, _, ref mut doc_string) => {
+                            // add a newline for extra padding between segments
+                            doc_string.push('\n');
+                        }
+                    _ => {}
+                }
+                docs.push(curr_frag);
+                last_frag = Some(frag);
+            } else {
+                match curr_frag {
+                    DocFragment::SugaredDoc(_, ref mut span, ref mut doc_string)
+                        | DocFragment::RawDoc(_, ref mut span, ref mut doc_string) => {
+                            doc_string.push('\n');
+                            doc_string.push_str(frag.as_str());
+                            *span = span.to(frag.span());
+                        }
+                    _ => unreachable!(),
+                }
+                last_frag = Some(curr_frag);
+            }
         } else {
-            // FIXME(eddyb) Is this still needed?
-            doc_string.push('\n');
-            self.doc_strings = vec![doc_string];
+            last_frag = Some(frag);
         }
     }
+
+    if let Some(frag) = last_frag.take() {
+        docs.push(frag);
+    }
+    *doc_strings = docs;
+}
+
+impl clean::Attributes {
+    pub fn collapse_doc_comments(&mut self) {
+        collapse(&mut self.doc_strings);
+    }
 }