about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-07-22 10:48:15 +0000
committerbors <bors@rust-lang.org>2018-07-22 10:48:15 +0000
commitd3b3bc57670ab91a53b2100cf3dfe78947bfe077 (patch)
tree76a30d5092074200894eab8b24181d88723075c1
parentaeca042f8464a98e1821756849f062eeede71e28 (diff)
parent88f264367954083554240fe1c491cb0a4d7c2cc2 (diff)
Auto merge of #52368 - GuillaumeGomez:intra_doc_link_resolution_failure-documented, r=QuietMisdreavus
Add "self" intra-link support

Fixes #49583.

r? @QuietMisdreavus
-rw-r--r--src/librustdoc/clean/mod.rs61
-rw-r--r--src/librustdoc/core.rs6
-rw-r--r--src/test/rustdoc/intra-link-self.rs39
3 files changed, 102 insertions, 4 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b7edf73f7ce..77521db835b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -20,7 +20,7 @@ pub use self::Visibility::{Public, Inherited};
 
 use rustc_target::spec::abi::Abi;
 use syntax;
-use syntax::ast::{self, AttrStyle, NodeId, Ident};
+use syntax::ast::{self, AttrStyle, Name, NodeId, Ident};
 use syntax::attr;
 use syntax::codemap::{dummy_spanned, Spanned};
 use syntax::feature_gate::UnstableFeatures;
@@ -39,6 +39,7 @@ use rustc::hir::{self, GenericArg, HirVec};
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::def_id::DefIndexAddressSpace;
+use rustc::hir::map::Node;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
 use rustc::middle::stability;
@@ -584,10 +585,23 @@ impl Clean<Item> for doctree::Module {
                                  .next()
                                  .map_or(true, |a| a.style == AttrStyle::Inner) {
             // inner doc comment, use the module's own scope for resolution
+            if self.id != NodeId::new(0) {
+                *cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(self.id));
+            } else {
+                *cx.current_item_name.borrow_mut() = None;
+            }
             cx.mod_ids.borrow_mut().push(self.id);
             self.attrs.clean(cx)
         } else {
             // outer doc comment, use its parent's scope
+            match cx.mod_ids.borrow().last() {
+                Some(parent) if *parent != NodeId::new(0) => {
+                    *cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(*parent));
+                }
+                _ => {
+                    *cx.current_item_name.borrow_mut() = None;
+                }
+            }
             let attrs = self.attrs.clean(cx);
             cx.mod_ids.borrow_mut().push(self.id);
             attrs
@@ -1165,11 +1179,17 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
         };
 
         let mut path = if let Some(second) = split.next() {
-            second
+            second.to_owned()
         } else {
             return Err(())
         };
 
+        if path == "self" || path == "Self" {
+            if let Some(name) = *cx.current_item_name.borrow() {
+                path = name.to_string();
+            }
+        }
+
         let ty = cx.resolver.borrow_mut()
                             .with_scope(*id,
             |resolver| {
@@ -2143,6 +2163,8 @@ impl Clean<Item> for doctree::Function {
         let (generics, decl) = enter_impl_trait(cx, || {
             (self.generics.clean(cx), (&self.decl, self.body).clean(cx))
         });
+
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -2321,6 +2343,7 @@ pub struct Trait {
 
 impl Clean<Item> for doctree::Trait {
     fn clean(&self, cx: &DocContext) -> Item {
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         let attrs = self.attrs.clean(cx);
         let is_spotlight = attrs.has_doc_flag("spotlight");
         Item {
@@ -2392,6 +2415,7 @@ impl Clean<Item> for hir::TraitItem {
                 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
             }
         };
+        *cx.current_item_name.borrow_mut() = Some(self.ident.name);
         Item {
             name: Some(self.ident.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -2424,6 +2448,7 @@ impl Clean<Item> for hir::ImplItem {
                 generics: Generics::default(),
             }, true),
         };
+        *cx.current_item_name.borrow_mut() = Some(self.ident.name);
         Item {
             name: Some(self.ident.name.clean(cx)),
             source: self.span.clean(cx),
@@ -3217,6 +3242,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
 
 impl Clean<Item> for hir::StructField {
     fn clean(&self, cx: &DocContext) -> Item {
+        *cx.current_item_name.borrow_mut() = Some(self.ident.name);
         Item {
             name: Some(self.ident.name).clean(cx),
             attrs: self.attrs.clean(cx),
@@ -3295,6 +3321,7 @@ impl Clean<Vec<Item>> for doctree::Struct {
         let name = self.name.clean(cx);
         let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
 
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         ret.push(Item {
             name: Some(name),
             attrs: self.attrs.clean(cx),
@@ -3320,6 +3347,7 @@ impl Clean<Vec<Item>> for doctree::Union {
         let name = self.name.clean(cx);
         let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
 
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         ret.push(Item {
             name: Some(name),
             attrs: self.attrs.clean(cx),
@@ -3372,6 +3400,7 @@ impl Clean<Vec<Item>> for doctree::Enum {
         let name = self.name.clean(cx);
         let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
 
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         ret.push(Item {
             name: Some(name),
             attrs: self.attrs.clean(cx),
@@ -3398,6 +3427,7 @@ pub struct Variant {
 
 impl Clean<Item> for doctree::Variant {
     fn clean(&self, cx: &DocContext) -> Item {
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -3693,6 +3723,7 @@ pub struct Typedef {
 
 impl Clean<Item> for doctree::Typedef {
     fn clean(&self, cx: &DocContext) -> Item {
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -3768,6 +3799,7 @@ pub struct Static {
 impl Clean<Item> for doctree::Static {
     fn clean(&self, cx: &DocContext) -> Item {
         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -3793,6 +3825,7 @@ pub struct Constant {
 
 impl Clean<Item> for doctree::Constant {
     fn clean(&self, cx: &DocContext) -> Item {
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -3862,6 +3895,23 @@ pub fn get_auto_traits_with_def_id(cx: &DocContext, id: DefId) -> Vec<Item> {
     finder.get_with_def_id(id)
 }
 
+fn get_name_if_possible(cx: &DocContext, node: NodeId) -> Option<Name> {
+    match cx.tcx.hir.get(node) {
+        Node::NodeItem(_) |
+        Node::NodeForeignItem(_) |
+        Node::NodeImplItem(_) |
+        Node::NodeTraitItem(_) |
+        Node::NodeVariant(_) |
+        Node::NodeField(_) |
+        Node::NodeLifetime(_) |
+        Node::NodeGenericParam(_) |
+        Node::NodeBinding(&hir::Pat { node: hir::PatKind::Binding(_,_,_,_), .. }) |
+        Node::NodeStructCtor(_) => {}
+        _ => return None,
+    }
+    Some(cx.tcx.hir.name(node))
+}
+
 impl Clean<Vec<Item>> for doctree::Impl {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
         let mut ret = Vec::new();
@@ -3881,6 +3931,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
                   .collect()
         }).unwrap_or(FxHashSet());
 
+        *cx.current_item_name.borrow_mut() = get_name_if_possible(cx, self.for_.id);
         ret.push(Item {
             name: None,
             attrs: self.attrs.clean(cx),
@@ -3967,6 +4018,7 @@ fn build_deref_target_impls(cx: &DocContext,
 
 impl Clean<Item> for doctree::ExternCrate {
     fn clean(&self, cx: &DocContext) -> Item {
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: None,
             attrs: self.attrs.clean(cx),
@@ -4013,6 +4065,8 @@ impl Clean<Vec<Item>> for doctree::Import {
             }
             Import::Simple(name.clean(cx), resolve_use_source(cx, path))
         };
+
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         vec![Item {
             name: None,
             attrs: self.attrs.clean(cx),
@@ -4081,6 +4135,8 @@ impl Clean<Item> for hir::ForeignItem {
                 ForeignTypeItem
             }
         };
+
+        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -4256,6 +4312,7 @@ pub struct Macro {
 impl Clean<Item> for doctree::Macro {
     fn clean(&self, cx: &DocContext) -> Item {
         let name = self.name.clean(cx);
+        *cx.current_item_name.borrow_mut() = None;
         Item {
             name: Some(name.clone()),
             attrs: self.attrs.clean(cx),
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 0a56c639220..375a9c981a1 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -25,7 +25,7 @@ use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::CStore;
 use rustc_target::spec::TargetTriple;
 
-use syntax::ast::NodeId;
+use syntax::ast::{Name, NodeId};
 use syntax::codemap;
 use syntax::edition::Edition;
 use syntax::feature_gate::UnstableFeatures;
@@ -82,7 +82,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
     pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
     pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
     /// Maps (type_id, trait_id) -> auto trait impl
-    pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>
+    pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>,
+    pub current_item_name: RefCell<Option<Name>>,
 }
 
 impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
@@ -383,6 +384,7 @@ pub fn run_core(search_paths: SearchPaths,
                 fake_def_ids: RefCell::new(FxHashMap()),
                 all_fake_def_ids: RefCell::new(FxHashSet()),
                 generated_synthetics: RefCell::new(FxHashSet()),
+                current_item_name: RefCell::new(None),
             };
             debug!("crate: {:?}", tcx.hir.krate());
 
diff --git a/src/test/rustdoc/intra-link-self.rs b/src/test/rustdoc/intra-link-self.rs
new file mode 100644
index 00000000000..21317f2af42
--- /dev/null
+++ b/src/test/rustdoc/intra-link-self.rs
@@ -0,0 +1,39 @@
+// Copyright 2018 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.
+
+#![crate_name = "foo"]
+
+// @has foo/index.html '//a/@href' '../foo/struct.Foo.html#method.new'
+// @has foo/struct.Foo.html '//a/@href' '../foo/struct.Foo.html#method.new'
+
+/// Use [`new`] to create a new instance.
+///
+/// [`new`]: Self::new
+pub struct Foo;
+
+impl Foo {
+    pub fn new() -> Self {
+        unimplemented!()
+    }
+}
+
+// @has foo/index.html '//a/@href' '../foo/struct.Bar.html#method.new2'
+// @has foo/struct.Bar.html '//a/@href' '../foo/struct.Bar.html#method.new2'
+
+/// Use [`new2`] to create a new instance.
+///
+/// [`new2`]: Self::new2
+pub struct Bar;
+
+impl Bar {
+    pub fn new2() -> Self {
+        unimplemented!()
+    }
+}