]> git.lizzy.rs Git - rust.git/commitdiff
rustdoc: Disambiguate anchors for assoc item impls
authorNick Platt <platt.nicholas@gmail.com>
Sat, 16 Apr 2016 15:46:52 +0000 (11:46 -0400)
committerNick Platt <platt.nicholas@gmail.com>
Mon, 18 Apr 2016 01:41:55 +0000 (21:41 -0400)
src/librustdoc/html/render.rs
src/test/rustdoc/issue-32890.rs [new file with mode: 0644]

index 864e10407d5ca780828e34b5fdcd9dc1aa3a5256..e873fd7569d9b0ca411314dab9dbe4f4c7fde869 100644 (file)
@@ -1903,10 +1903,11 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     if t.items.is_empty() {
         write!(w, "{{ }}")?;
     } else {
+        // FIXME: we should be using a derived_id for the Anchors here
         write!(w, "{{\n")?;
         for t in &types {
             write!(w, "    ")?;
-            render_assoc_item(w, t, AssocItemLink::Anchor)?;
+            render_assoc_item(w, t, AssocItemLink::Anchor(None))?;
             write!(w, ";\n")?;
         }
         if !types.is_empty() && !consts.is_empty() {
@@ -1914,7 +1915,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for t in &consts {
             write!(w, "    ")?;
-            render_assoc_item(w, t, AssocItemLink::Anchor)?;
+            render_assoc_item(w, t, AssocItemLink::Anchor(None))?;
             write!(w, ";\n")?;
         }
         if !consts.is_empty() && !required.is_empty() {
@@ -1922,7 +1923,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &required {
             write!(w, "    ")?;
-            render_assoc_item(w, m, AssocItemLink::Anchor)?;
+            render_assoc_item(w, m, AssocItemLink::Anchor(None))?;
             write!(w, ";\n")?;
         }
         if !required.is_empty() && !provided.is_empty() {
@@ -1930,7 +1931,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &provided {
             write!(w, "    ")?;
-            render_assoc_item(w, m, AssocItemLink::Anchor)?;
+            render_assoc_item(w, m, AssocItemLink::Anchor(None))?;
             write!(w, " {{ ... }}\n")?;
         }
         write!(w, "}}")?;
@@ -1947,7 +1948,7 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
         write!(w, "<h3 id='{id}' class='method stab {stab}'><code>",
                id = id,
                stab = m.stability_class())?;
-        render_assoc_item(w, m, AssocItemLink::Anchor)?;
+        render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)))?;
         write!(w, "</code>")?;
         render_stability_since(w, m, t)?;
         write!(w, "</h3>")?;
@@ -2042,7 +2043,8 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink) -> String {
 
     let anchor = format!("#{}.{}", ty, name);
     match link {
-        AssocItemLink::Anchor => anchor,
+        AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
+        AssocItemLink::Anchor(None) => anchor,
         AssocItemLink::GotoSource(did, _) => {
             href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
         }
@@ -2117,7 +2119,8 @@ fn method(w: &mut fmt::Formatter,
         let name = meth.name.as_ref().unwrap();
         let anchor = format!("#{}.{}", shortty(meth), name);
         let href = match link {
-            AssocItemLink::Anchor => anchor,
+            AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
+            AssocItemLink::Anchor(None) => anchor,
             AssocItemLink::GotoSource(did, provided_methods) => {
                 // We're creating a link from an impl-item to the corresponding
                 // trait-item and need to map the anchored type accordingly.
@@ -2378,10 +2381,19 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
 
 #[derive(Copy, Clone)]
 enum AssocItemLink<'a> {
-    Anchor,
+    Anchor(Option<&'a str>),
     GotoSource(DefId, &'a HashSet<String>),
 }
 
+impl<'a> AssocItemLink<'a> {
+    fn anchor(&self, id: &'a String) -> Self {
+        match *self {
+            AssocItemLink::Anchor(_) => { AssocItemLink::Anchor(Some(&id)) },
+            ref other => *other,
+        }
+    }
+}
+
 enum AssocItemRender<'a> {
     All,
     DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type },
@@ -2413,7 +2425,7 @@ fn render_assoc_items(w: &mut fmt::Formatter,
             }
         };
         for i in &non_trait {
-            render_impl(w, cx, i, AssocItemLink::Anchor, render_header,
+            render_impl(w, cx, i, AssocItemLink::Anchor(None), render_header,
                         containing_item.stable_since())?;
         }
     }
@@ -2509,32 +2521,32 @@ fn doctraititem(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
                     write!(w, "<h4 id='{}' class='{}'>", id, shortty)?;
                     render_stability_since_raw(w, item.stable_since(), outer_version)?;
                     write!(w, "<code>")?;
-                    render_assoc_item(w, item, link)?;
+                    render_assoc_item(w, item, link.anchor(&id))?;
                     write!(w, "</code></h4>\n")?;
                 }
             }
             clean::TypedefItem(ref tydef, _) => {
                 let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name));
                 write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
-                assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link)?;
+                assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
                 write!(w, "</code></h4>\n")?;
             }
             clean::AssociatedConstItem(ref ty, ref default) => {
                 let id = derive_id(format!("{}.{}", shortty, name));
                 write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
-                assoc_const(w, item, ty, default.as_ref(), link)?;
+                assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
                 write!(w, "</code></h4>\n")?;
             }
             clean::ConstantItem(ref c) => {
                 let id = derive_id(format!("{}.{}", shortty, name));
                 write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
-                assoc_const(w, item, &c.type_, Some(&c.expr), link)?;
+                assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?;
                 write!(w, "</code></h4>\n")?;
             }
             clean::AssociatedTypeItem(ref bounds, ref default) => {
                 let id = derive_id(format!("{}.{}", shortty, name));
                 write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
-                assoc_type(w, item, bounds, default.as_ref(), link)?;
+                assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
                 write!(w, "</code></h4>\n")?;
             }
             clean::StrippedItem(..) => return Ok(()),
diff --git a/src/test/rustdoc/issue-32890.rs b/src/test/rustdoc/issue-32890.rs
new file mode 100644 (file)
index 0000000..ef62f12
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// @has issue_32890/struct.Foo.html
+pub struct Foo<T>(T);
+
+impl Foo<u8> {
+    // @has - '//a[@href="#method.pass"]' 'pass'
+    pub fn pass() {}
+}
+
+impl Foo<u16> {
+    // @has - '//a[@href="#method.pass-1"]' 'pass'
+    pub fn pass() {}
+}
+
+impl Foo<u32> {
+    // @has - '//a[@href="#method.pass-2"]' 'pass'
+    pub fn pass() {}
+}