Skip to content

Commit 4ab8aa3

Browse files
Add support for intra-doc link fields of enum variant
1 parent 4993807 commit 4ab8aa3

File tree

2 files changed

+74
-7
lines changed

2 files changed

+74
-7
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,59 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
5656
}
5757
}
5858

59+
fn variant_field(
60+
&self,
61+
path_str: &str,
62+
current_item: &Option<String>,
63+
module_id: syntax::ast::NodeId,
64+
) -> Result<(Res, Option<String>), ()> {
65+
let cx = self.cx;
66+
67+
let mut split = path_str.rsplitn(3, "::");
68+
let variant_field_name = split.next().map(|f| Symbol::intern(f)).ok_or(())?;
69+
let variant_name = split.next().map(|f| Symbol::intern(f)).ok_or(())?;
70+
let path = split.next().map(|f| {
71+
if f == "self" || f == "Self" {
72+
if let Some(name) = current_item.as_ref() {
73+
return name.clone();
74+
}
75+
}
76+
f.to_owned()
77+
}).ok_or(())?;
78+
let (_, ty_res) = cx.enter_resolver(|resolver| {
79+
resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
80+
})?;
81+
if let Res::Err = ty_res {
82+
return Err(());
83+
}
84+
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
85+
match ty_res {
86+
Res::Def(DefKind::Enum, did) => {
87+
let item = cx.tcx.inherent_impls(did)
88+
.iter()
89+
.flat_map(|imp| cx.tcx.associated_items(*imp))
90+
.find(|item| item.ident.name == variant_name);
91+
if item.is_some() {
92+
return Err(());
93+
}
94+
match cx.tcx.type_of(did).kind {
95+
ty::Adt(def, _) if def.is_enum() => {
96+
if def.all_fields()
97+
.find(|item| item.ident.name == variant_field_name).is_some() {
98+
Ok((ty_res,
99+
Some(format!("variant.{}.field.{}",
100+
variant_name, variant_field_name))))
101+
} else {
102+
Err(())
103+
}
104+
}
105+
_ => Err(()),
106+
}
107+
}
108+
_ => Err(())
109+
}
110+
}
111+
59112
/// Resolves a string as a path within a particular namespace. Also returns an optional
60113
/// URL fragment in the case of variants and methods.
61114
fn resolve(
@@ -149,7 +202,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
149202
resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
150203
}).map_err(|_| ErrorKind::ResolutionFailure)?;
151204
if let Res::Err = ty_res {
152-
return Err(ErrorKind::ResolutionFailure);
205+
return self.variant_field(path_str, current_item, module_id);
153206
}
154207
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
155208
match ty_res {
@@ -165,7 +218,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
165218
let out = match item.kind {
166219
ty::AssocKind::Method if ns == ValueNS => "method",
167220
ty::AssocKind::Const if ns == ValueNS => "associatedconstant",
168-
_ => return Err(ErrorKind::ResolutionFailure)
221+
_ => return self.variant_field(path_str, current_item, module_id),
169222
};
170223
if extra_fragment.is_some() {
171224
Err(ErrorKind::AnchorFailure(
@@ -206,10 +259,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
206259
item.ident))))
207260
}
208261
} else {
209-
Err(ErrorKind::ResolutionFailure)
262+
self.variant_field(path_str, current_item, module_id)
210263
}
211264
}
212-
_ => Err(ErrorKind::ResolutionFailure),
265+
_ => self.variant_field(path_str, current_item, module_id),
213266
}
214267
}
215268
}
@@ -228,7 +281,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
228281
"tymethod"
229282
}
230283
}
231-
_ => return Err(ErrorKind::ResolutionFailure)
284+
_ => return self.variant_field(path_str, current_item, module_id),
232285
};
233286

234287
if extra_fragment.is_some() {
@@ -244,10 +297,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
244297
Ok((ty_res, Some(format!("{}.{}", kind, item_name))))
245298
}
246299
} else {
247-
Err(ErrorKind::ResolutionFailure)
300+
self.variant_field(path_str, current_item, module_id)
248301
}
249302
}
250-
_ => Err(ErrorKind::ResolutionFailure)
303+
_ => self.variant_field(path_str, current_item, module_id),
251304
}
252305
} else {
253306
debug!("attempting to resolve item without parent module: {}", path_str);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![crate_name = "foo"]
2+
3+
pub enum Foo {
4+
X {
5+
y: u8,
6+
}
7+
}
8+
9+
/// Hello
10+
///
11+
/// I want [Foo::X::y].
12+
pub fn foo() {}
13+
14+
// @has foo/fn.foo.html '//a/@href' '../foo/enum.Foo.html#variant.X.field.y'

0 commit comments

Comments
 (0)