Skip to content

Commit 88f2643

Browse files
Add "self" intra-link support
1 parent 6cc42a4 commit 88f2643

File tree

3 files changed

+102
-4
lines changed

3 files changed

+102
-4
lines changed

src/librustdoc/clean/mod.rs

+59-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use self::Visibility::{Public, Inherited};
2020

2121
use rustc_target::spec::abi::Abi;
2222
use syntax;
23-
use syntax::ast::{self, AttrStyle, NodeId, Ident};
23+
use syntax::ast::{self, AttrStyle, Name, NodeId, Ident};
2424
use syntax::attr;
2525
use syntax::codemap::{dummy_spanned, Spanned};
2626
use syntax::feature_gate::UnstableFeatures;
@@ -39,6 +39,7 @@ use rustc::hir::{self, GenericArg, HirVec};
3939
use rustc::hir::def::{self, Def, CtorKind};
4040
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
4141
use rustc::hir::def_id::DefIndexAddressSpace;
42+
use rustc::hir::map::Node;
4243
use rustc::ty::subst::Substs;
4344
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
4445
use rustc::middle::stability;
@@ -576,10 +577,23 @@ impl Clean<Item> for doctree::Module {
576577
.next()
577578
.map_or(true, |a| a.style == AttrStyle::Inner) {
578579
// inner doc comment, use the module's own scope for resolution
580+
if self.id != NodeId::new(0) {
581+
*cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(self.id));
582+
} else {
583+
*cx.current_item_name.borrow_mut() = None;
584+
}
579585
cx.mod_ids.borrow_mut().push(self.id);
580586
self.attrs.clean(cx)
581587
} else {
582588
// outer doc comment, use its parent's scope
589+
match cx.mod_ids.borrow().last() {
590+
Some(parent) if *parent != NodeId::new(0) => {
591+
*cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(*parent));
592+
}
593+
_ => {
594+
*cx.current_item_name.borrow_mut() = None;
595+
}
596+
}
583597
let attrs = self.attrs.clean(cx);
584598
cx.mod_ids.borrow_mut().push(self.id);
585599
attrs
@@ -1132,11 +1146,17 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
11321146
};
11331147

11341148
let mut path = if let Some(second) = split.next() {
1135-
second
1149+
second.to_owned()
11361150
} else {
11371151
return Err(())
11381152
};
11391153

1154+
if path == "self" || path == "Self" {
1155+
if let Some(name) = *cx.current_item_name.borrow() {
1156+
path = name.to_string();
1157+
}
1158+
}
1159+
11401160
let ty = cx.resolver.borrow_mut()
11411161
.with_scope(*id,
11421162
|resolver| {
@@ -2110,6 +2130,8 @@ impl Clean<Item> for doctree::Function {
21102130
let (generics, decl) = enter_impl_trait(cx, || {
21112131
(self.generics.clean(cx), (&self.decl, self.body).clean(cx))
21122132
});
2133+
2134+
*cx.current_item_name.borrow_mut() = Some(self.name);
21132135
Item {
21142136
name: Some(self.name.clean(cx)),
21152137
attrs: self.attrs.clean(cx),
@@ -2288,6 +2310,7 @@ pub struct Trait {
22882310

22892311
impl Clean<Item> for doctree::Trait {
22902312
fn clean(&self, cx: &DocContext) -> Item {
2313+
*cx.current_item_name.borrow_mut() = Some(self.name);
22912314
let attrs = self.attrs.clean(cx);
22922315
let is_spotlight = attrs.has_doc_flag("spotlight");
22932316
Item {
@@ -2359,6 +2382,7 @@ impl Clean<Item> for hir::TraitItem {
23592382
AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
23602383
}
23612384
};
2385+
*cx.current_item_name.borrow_mut() = Some(self.ident.name);
23622386
Item {
23632387
name: Some(self.ident.name.clean(cx)),
23642388
attrs: self.attrs.clean(cx),
@@ -2387,6 +2411,7 @@ impl Clean<Item> for hir::ImplItem {
23872411
generics: Generics::default(),
23882412
}, true),
23892413
};
2414+
*cx.current_item_name.borrow_mut() = Some(self.ident.name);
23902415
Item {
23912416
name: Some(self.ident.name.clean(cx)),
23922417
source: self.span.clean(cx),
@@ -3179,6 +3204,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
31793204

31803205
impl Clean<Item> for hir::StructField {
31813206
fn clean(&self, cx: &DocContext) -> Item {
3207+
*cx.current_item_name.borrow_mut() = Some(self.ident.name);
31823208
Item {
31833209
name: Some(self.ident.name).clean(cx),
31843210
attrs: self.attrs.clean(cx),
@@ -3257,6 +3283,7 @@ impl Clean<Vec<Item>> for doctree::Struct {
32573283
let name = self.name.clean(cx);
32583284
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
32593285

3286+
*cx.current_item_name.borrow_mut() = Some(self.name);
32603287
ret.push(Item {
32613288
name: Some(name),
32623289
attrs: self.attrs.clean(cx),
@@ -3282,6 +3309,7 @@ impl Clean<Vec<Item>> for doctree::Union {
32823309
let name = self.name.clean(cx);
32833310
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
32843311

3312+
*cx.current_item_name.borrow_mut() = Some(self.name);
32853313
ret.push(Item {
32863314
name: Some(name),
32873315
attrs: self.attrs.clean(cx),
@@ -3334,6 +3362,7 @@ impl Clean<Vec<Item>> for doctree::Enum {
33343362
let name = self.name.clean(cx);
33353363
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
33363364

3365+
*cx.current_item_name.borrow_mut() = Some(self.name);
33373366
ret.push(Item {
33383367
name: Some(name),
33393368
attrs: self.attrs.clean(cx),
@@ -3360,6 +3389,7 @@ pub struct Variant {
33603389

33613390
impl Clean<Item> for doctree::Variant {
33623391
fn clean(&self, cx: &DocContext) -> Item {
3392+
*cx.current_item_name.borrow_mut() = Some(self.name);
33633393
Item {
33643394
name: Some(self.name.clean(cx)),
33653395
attrs: self.attrs.clean(cx),
@@ -3655,6 +3685,7 @@ pub struct Typedef {
36553685

36563686
impl Clean<Item> for doctree::Typedef {
36573687
fn clean(&self, cx: &DocContext) -> Item {
3688+
*cx.current_item_name.borrow_mut() = Some(self.name);
36583689
Item {
36593690
name: Some(self.name.clean(cx)),
36603691
attrs: self.attrs.clean(cx),
@@ -3706,6 +3737,7 @@ pub struct Static {
37063737
impl Clean<Item> for doctree::Static {
37073738
fn clean(&self, cx: &DocContext) -> Item {
37083739
debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
3740+
*cx.current_item_name.borrow_mut() = Some(self.name);
37093741
Item {
37103742
name: Some(self.name.clean(cx)),
37113743
attrs: self.attrs.clean(cx),
@@ -3731,6 +3763,7 @@ pub struct Constant {
37313763

37323764
impl Clean<Item> for doctree::Constant {
37333765
fn clean(&self, cx: &DocContext) -> Item {
3766+
*cx.current_item_name.borrow_mut() = Some(self.name);
37343767
Item {
37353768
name: Some(self.name.clean(cx)),
37363769
attrs: self.attrs.clean(cx),
@@ -3800,6 +3833,23 @@ pub fn get_auto_traits_with_def_id(cx: &DocContext, id: DefId) -> Vec<Item> {
38003833
finder.get_with_def_id(id)
38013834
}
38023835

3836+
fn get_name_if_possible(cx: &DocContext, node: NodeId) -> Option<Name> {
3837+
match cx.tcx.hir.get(node) {
3838+
Node::NodeItem(_) |
3839+
Node::NodeForeignItem(_) |
3840+
Node::NodeImplItem(_) |
3841+
Node::NodeTraitItem(_) |
3842+
Node::NodeVariant(_) |
3843+
Node::NodeField(_) |
3844+
Node::NodeLifetime(_) |
3845+
Node::NodeGenericParam(_) |
3846+
Node::NodeBinding(&hir::Pat { node: hir::PatKind::Binding(_,_,_,_), .. }) |
3847+
Node::NodeStructCtor(_) => {}
3848+
_ => return None,
3849+
}
3850+
Some(cx.tcx.hir.name(node))
3851+
}
3852+
38033853
impl Clean<Vec<Item>> for doctree::Impl {
38043854
fn clean(&self, cx: &DocContext) -> Vec<Item> {
38053855
let mut ret = Vec::new();
@@ -3819,6 +3869,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
38193869
.collect()
38203870
}).unwrap_or(FxHashSet());
38213871

3872+
*cx.current_item_name.borrow_mut() = get_name_if_possible(cx, self.for_.id);
38223873
ret.push(Item {
38233874
name: None,
38243875
attrs: self.attrs.clean(cx),
@@ -3905,6 +3956,7 @@ fn build_deref_target_impls(cx: &DocContext,
39053956

39063957
impl Clean<Item> for doctree::ExternCrate {
39073958
fn clean(&self, cx: &DocContext) -> Item {
3959+
*cx.current_item_name.borrow_mut() = Some(self.name);
39083960
Item {
39093961
name: None,
39103962
attrs: self.attrs.clean(cx),
@@ -3951,6 +4003,8 @@ impl Clean<Vec<Item>> for doctree::Import {
39514003
}
39524004
Import::Simple(name.clean(cx), resolve_use_source(cx, path))
39534005
};
4006+
4007+
*cx.current_item_name.borrow_mut() = Some(self.name);
39544008
vec![Item {
39554009
name: None,
39564010
attrs: self.attrs.clean(cx),
@@ -4019,6 +4073,8 @@ impl Clean<Item> for hir::ForeignItem {
40194073
ForeignTypeItem
40204074
}
40214075
};
4076+
4077+
*cx.current_item_name.borrow_mut() = Some(self.name);
40224078
Item {
40234079
name: Some(self.name.clean(cx)),
40244080
attrs: self.attrs.clean(cx),
@@ -4194,6 +4250,7 @@ pub struct Macro {
41944250
impl Clean<Item> for doctree::Macro {
41954251
fn clean(&self, cx: &DocContext) -> Item {
41964252
let name = self.name.clean(cx);
4253+
*cx.current_item_name.borrow_mut() = None;
41974254
Item {
41984255
name: Some(name.clone()),
41994256
attrs: self.attrs.clean(cx),

src/librustdoc/core.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_metadata::creader::CrateLoader;
2525
use rustc_metadata::cstore::CStore;
2626
use rustc_target::spec::TargetTriple;
2727

28-
use syntax::ast::NodeId;
28+
use syntax::ast::{Name, NodeId};
2929
use syntax::codemap;
3030
use syntax::edition::Edition;
3131
use syntax::feature_gate::UnstableFeatures;
@@ -82,7 +82,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
8282
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
8383
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
8484
/// Maps (type_id, trait_id) -> auto trait impl
85-
pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>
85+
pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>,
86+
pub current_item_name: RefCell<Option<Name>>,
8687
}
8788

8889
impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
@@ -383,6 +384,7 @@ pub fn run_core(search_paths: SearchPaths,
383384
fake_def_ids: RefCell::new(FxHashMap()),
384385
all_fake_def_ids: RefCell::new(FxHashSet()),
385386
generated_synthetics: RefCell::new(FxHashSet()),
387+
current_item_name: RefCell::new(None),
386388
};
387389
debug!("crate: {:?}", tcx.hir.krate());
388390

src/test/rustdoc/intra-link-self.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_name = "foo"]
12+
13+
// @has foo/index.html '//a/@href' '../foo/struct.Foo.html#method.new'
14+
// @has foo/struct.Foo.html '//a/@href' '../foo/struct.Foo.html#method.new'
15+
16+
/// Use [`new`] to create a new instance.
17+
///
18+
/// [`new`]: Self::new
19+
pub struct Foo;
20+
21+
impl Foo {
22+
pub fn new() -> Self {
23+
unimplemented!()
24+
}
25+
}
26+
27+
// @has foo/index.html '//a/@href' '../foo/struct.Bar.html#method.new2'
28+
// @has foo/struct.Bar.html '//a/@href' '../foo/struct.Bar.html#method.new2'
29+
30+
/// Use [`new2`] to create a new instance.
31+
///
32+
/// [`new2`]: Self::new2
33+
pub struct Bar;
34+
35+
impl Bar {
36+
pub fn new2() -> Self {
37+
unimplemented!()
38+
}
39+
}

0 commit comments

Comments
 (0)