]> git.lizzy.rs Git - rust.git/commitdiff
librustdoc: improve testnames for doctests
authorKevin Butler <haqkrs@gmail.com>
Wed, 4 Nov 2015 23:41:33 +0000 (23:41 +0000)
committerKevin Butler <haqkrs@gmail.com>
Fri, 6 Nov 2015 00:37:32 +0000 (00:37 +0000)
src/librustdoc/clean/mod.rs
src/librustdoc/test.rs

index dbd1106b6a1387cc2e4205a8ee056a875b895c83..34ddd5726d38525f67467ef2d688def91f3c8eef 100644 (file)
@@ -2568,8 +2568,18 @@ fn resolve_type(cx: &DocContext,
     debug!("resolve_type({:?},{:?})", path, id);
     let tcx = match cx.tcx_opt() {
         Some(tcx) => tcx,
-        // If we're extracting tests, this return value doesn't matter.
-        None => return Primitive(Bool),
+        // If we're extracting tests, this return value's accuracy is not
+        // important, all we want is a string representation to help people
+        // figure out what doctests are failing.
+        None => {
+            let did = DefId::local(DefIndex::from_u32(0));
+            return ResolvedPath {
+                path: path,
+                typarams: None,
+                did: did,
+                is_generic: false
+            };
+        }
     };
     let def = match tcx.def_map.borrow().get(&id) {
         Some(k) => k.full_def(),
index cbaff95dfddd730fddb73369a0bcd6fb8f30aa82..1ea30a8763e40df05c77540b8383f58a64a851be 100644 (file)
@@ -422,22 +422,59 @@ pub fn register_header(&mut self, name: &str, level: u32) {
 
 impl DocFolder for Collector {
     fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
-        let pushed = match item.name {
-            Some(ref name) if name.is_empty() => false,
-            Some(ref name) => { self.names.push(name.to_string()); true }
-            None => false
+        let current_name = match item.name {
+            Some(ref name) if !name.is_empty() => Some(name.clone()),
+            _ => typename_if_impl(&item)
         };
-        match item.doc_value() {
-            Some(doc) => {
-                self.cnt = 0;
-                markdown::find_testable_code(doc, &mut *self);
-            }
-            None => {}
+
+        let pushed = if let Some(name) = current_name {
+            self.names.push(name);
+            true
+        } else {
+            false
+        };
+
+        if let Some(doc) = item.doc_value() {
+            self.cnt = 0;
+            markdown::find_testable_code(doc, &mut *self);
         }
+
         let ret = self.fold_item_recur(item);
         if pushed {
             self.names.pop();
         }
+
         return ret;
+
+        // FIXME: it would be better to not have the escaped version in the first place
+        fn unescape_for_testname(mut s: String) -> String {
+            // for refs `&foo`
+            if s.contains("&amp;") {
+                s = s.replace("&amp;", "&");
+
+                // `::&'a mut Foo::` looks weird, let's make it `::<&'a mut Foo>`::
+                if let Some('&') = s.chars().nth(0) {
+                    s = format!("<{}>", s);
+                }
+            }
+
+            // either `<..>` or `->`
+            if s.contains("&gt;") {
+                s.replace("&gt;", ">")
+                 .replace("&lt;", "<")
+            } else {
+                s
+            }
+        }
+
+        fn typename_if_impl(item: &clean::Item) -> Option<String> {
+            if let clean::ItemEnum::ImplItem(ref impl_) = item.inner {
+                let path = impl_.for_.to_string();
+                let unescaped_path = unescape_for_testname(path);
+                Some(unescaped_path)
+            } else {
+                None
+            }
+        }
     }
 }