Skip to content

Commit ebee483

Browse files
Add doc keyword support
1 parent d024d6a commit ebee483

File tree

10 files changed

+166
-56
lines changed

10 files changed

+166
-56
lines changed

src/librustdoc/clean/mod.rs

+63-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use syntax::attr;
2626
use syntax::codemap::{dummy_spanned, Spanned};
2727
use syntax::feature_gate::UnstableFeatures;
2828
use syntax::ptr::P;
29-
use syntax::symbol::keywords;
29+
use syntax::symbol::keywords::{self, Keyword};
3030
use syntax::symbol::{Symbol, InternedString};
3131
use syntax_pos::{self, DUMMY_SP, Pos, FileName};
3232

@@ -54,6 +54,7 @@ use std::{mem, slice, vec};
5454
use std::iter::{FromIterator, once};
5555
use rustc_data_structures::sync::Lrc;
5656
use std::rc::Rc;
57+
use std::str::FromStr;
5758
use std::cell::RefCell;
5859
use std::sync::Arc;
5960
use std::u32;
@@ -177,7 +178,7 @@ impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx>
177178
_ => unreachable!(),
178179
}
179180

180-
let ExternalCrate { name, src, primitives, .. } = LOCAL_CRATE.clean(cx);
181+
let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
181182
{
182183
let m = match module.inner {
183184
ModuleItem(ref mut m) => m,
@@ -195,6 +196,18 @@ impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx>
195196
inner: PrimitiveItem(prim),
196197
}
197198
}));
199+
m.items.extend(keywords.iter().map(|&(def_id, ref kw, ref attrs)| {
200+
Item {
201+
source: Span::empty(),
202+
name: Some(kw.clone()),
203+
attrs: attrs.clone(),
204+
visibility: Some(Public),
205+
stability: get_stability(cx, def_id),
206+
deprecation: get_deprecation(cx, def_id),
207+
def_id,
208+
inner: KeywordItem(kw.clone()),
209+
}
210+
}));
198211
}
199212

200213
let mut access_levels = cx.access_levels.borrow_mut();
@@ -220,6 +233,7 @@ pub struct ExternalCrate {
220233
pub src: FileName,
221234
pub attrs: Attributes,
222235
pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
236+
pub keywords: Vec<(DefId, String, Attributes)>,
223237
}
224238

225239
impl Clean<ExternalCrate> for CrateNum {
@@ -286,11 +300,54 @@ impl Clean<ExternalCrate> for CrateNum {
286300
.filter_map(as_primitive).collect()
287301
};
288302

303+
let as_keyword = |def: Def| {
304+
if let Def::Mod(def_id) = def {
305+
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
306+
let mut keyword = None;
307+
for attr in attrs.lists("doc") {
308+
if let Some(v) = attr.value_str() {
309+
if attr.check_name("keyword") {
310+
keyword = Keyword::from_str(&v.as_str()).ok()
311+
.map(|x| x.name().to_string());
312+
if keyword.is_some() {
313+
break
314+
}
315+
// FIXME: should warn on unknown keywords?
316+
}
317+
}
318+
}
319+
return keyword.map(|p| (def_id, p, attrs));
320+
}
321+
None
322+
};
323+
let keywords = if root.is_local() {
324+
cx.tcx.hir.krate().module.item_ids.iter().filter_map(|&id| {
325+
let item = cx.tcx.hir.expect_item(id.id);
326+
match item.node {
327+
hir::ItemMod(_) => {
328+
as_keyword(Def::Mod(cx.tcx.hir.local_def_id(id.id)))
329+
}
330+
hir::ItemUse(ref path, hir::UseKind::Single)
331+
if item.vis == hir::Visibility::Public => {
332+
as_keyword(path.def).map(|(_, prim, attrs)| {
333+
// Pretend the primitive is local.
334+
(cx.tcx.hir.local_def_id(id.id), prim, attrs)
335+
})
336+
}
337+
_ => None
338+
}
339+
}).collect()
340+
} else {
341+
cx.tcx.item_children(root).iter().map(|item| item.def)
342+
.filter_map(as_keyword).collect()
343+
};
344+
289345
ExternalCrate {
290346
name: cx.tcx.crate_name(*self).to_string(),
291347
src: krate_src,
292348
attrs: cx.tcx.get_attrs(root).clean(cx),
293349
primitives,
350+
keywords,
294351
}
295352
}
296353
}
@@ -397,6 +454,9 @@ impl Item {
397454
pub fn is_extern_crate(&self) -> bool {
398455
self.type_() == ItemType::ExternCrate
399456
}
457+
pub fn is_keyword(&self) -> bool {
458+
self.type_() == ItemType::Keyword
459+
}
400460

401461
pub fn is_stripped(&self) -> bool {
402462
match self.inner { StrippedItem(..) => true, _ => false }
@@ -475,6 +535,7 @@ pub enum ItemEnum {
475535
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
476536
/// An item that has been stripped by a rustdoc pass
477537
StrippedItem(Box<ItemEnum>),
538+
KeywordItem(String),
478539
}
479540

480541
impl ItemEnum {

src/librustdoc/html/item_type.rs

+8
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub enum ItemType {
4242
AssociatedConst = 18,
4343
Union = 19,
4444
ForeignType = 20,
45+
Keyword = 21,
4546
}
4647

4748

@@ -50,6 +51,7 @@ pub enum NameSpace {
5051
Type,
5152
Value,
5253
Macro,
54+
Keyword,
5355
}
5456

5557
impl<'a> From<&'a clean::Item> for ItemType {
@@ -83,6 +85,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
8385
clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
8486
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
8587
clean::ForeignTypeItem => ItemType::ForeignType,
88+
clean::KeywordItem(..) => ItemType::Keyword,
8689
clean::StrippedItem(..) => unreachable!(),
8790
}
8891
}
@@ -131,6 +134,7 @@ impl ItemType {
131134
ItemType::Constant => "constant",
132135
ItemType::AssociatedConst => "associatedconstant",
133136
ItemType::ForeignType => "foreigntype",
137+
ItemType::Keyword => "keyword",
134138
}
135139
}
136140

@@ -159,6 +163,8 @@ impl ItemType {
159163
ItemType::AssociatedConst => NameSpace::Value,
160164

161165
ItemType::Macro => NameSpace::Macro,
166+
167+
ItemType::Keyword => NameSpace::Keyword,
162168
}
163169
}
164170
}
@@ -172,13 +178,15 @@ impl fmt::Display for ItemType {
172178
pub const NAMESPACE_TYPE: &'static str = "t";
173179
pub const NAMESPACE_VALUE: &'static str = "v";
174180
pub const NAMESPACE_MACRO: &'static str = "m";
181+
pub const NAMESPACE_KEYWORD: &'static str = "k";
175182

176183
impl NameSpace {
177184
pub fn to_static_str(&self) -> &'static str {
178185
match *self {
179186
NameSpace::Type => NAMESPACE_TYPE,
180187
NameSpace::Value => NAMESPACE_VALUE,
181188
NameSpace::Macro => NAMESPACE_MACRO,
189+
NameSpace::Keyword => NAMESPACE_KEYWORD,
182190
}
183191
}
184192
}

src/librustdoc/html/render.rs

+41-47
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,7 @@ struct AllTypes {
15411541
typedefs: HashSet<ItemEntry>,
15421542
statics: HashSet<ItemEntry>,
15431543
constants: HashSet<ItemEntry>,
1544+
keywords: HashSet<ItemEntry>,
15441545
}
15451546

15461547
impl AllTypes {
@@ -1556,6 +1557,7 @@ impl AllTypes {
15561557
typedefs: HashSet::with_capacity(100),
15571558
statics: HashSet::with_capacity(100),
15581559
constants: HashSet::with_capacity(100),
1560+
keywords: HashSet::with_capacity(10),
15591561
}
15601562
}
15611563

@@ -2063,12 +2065,13 @@ impl<'a> fmt::Display for Item<'a> {
20632065
clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
20642066
clean::ConstantItem(..) => write!(fmt, "Constant ")?,
20652067
clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?,
2068+
clean::KeywordItem(..) => write!(fmt, "Keyword ")?,
20662069
_ => {
20672070
// We don't generate pages for any other type.
20682071
unreachable!();
20692072
}
20702073
}
2071-
if !self.item.is_primitive() {
2074+
if !self.item.is_primitive() && !self.item.is_keyword() {
20722075
let cur = &self.cx.current;
20732076
let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() };
20742077
for (i, component) in cur.iter().enumerate().take(amt) {
@@ -2126,6 +2129,7 @@ impl<'a> fmt::Display for Item<'a> {
21262129
item_static(fmt, self.cx, self.item, i),
21272130
clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c),
21282131
clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item),
2132+
clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k),
21292133
_ => {
21302134
// We don't generate pages for any other type.
21312135
unreachable!();
@@ -2353,29 +2357,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
23532357
write!(w, "</table>")?;
23542358
}
23552359
curty = myty;
2356-
let (short, name) = match myty.unwrap() {
2357-
ItemType::ExternCrate |
2358-
ItemType::Import => ("reexports", "Re-exports"),
2359-
ItemType::Module => ("modules", "Modules"),
2360-
ItemType::Struct => ("structs", "Structs"),
2361-
ItemType::Union => ("unions", "Unions"),
2362-
ItemType::Enum => ("enums", "Enums"),
2363-
ItemType::Function => ("functions", "Functions"),
2364-
ItemType::Typedef => ("types", "Type Definitions"),
2365-
ItemType::Static => ("statics", "Statics"),
2366-
ItemType::Constant => ("constants", "Constants"),
2367-
ItemType::Trait => ("traits", "Traits"),
2368-
ItemType::Impl => ("impls", "Implementations"),
2369-
ItemType::TyMethod => ("tymethods", "Type Methods"),
2370-
ItemType::Method => ("methods", "Methods"),
2371-
ItemType::StructField => ("fields", "Struct Fields"),
2372-
ItemType::Variant => ("variants", "Variants"),
2373-
ItemType::Macro => ("macros", "Macros"),
2374-
ItemType::Primitive => ("primitives", "Primitive Types"),
2375-
ItemType::AssociatedType => ("associated-types", "Associated Types"),
2376-
ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
2377-
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
2378-
};
2360+
let (short, name) = item_ty_to_strs(&myty.unwrap());
23792361
write!(w, "<h2 id='{id}' class='section-header'>\
23802362
<a href=\"#{id}\">{name}</a></h2>\n<table>",
23812363
id = derive_id(short.to_owned()), name = name)?;
@@ -4360,6 +4342,33 @@ fn sidebar_enum(fmt: &mut fmt::Formatter, it: &clean::Item,
43604342
Ok(())
43614343
}
43624344

4345+
fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) {
4346+
match *ty {
4347+
ItemType::ExternCrate |
4348+
ItemType::Import => ("reexports", "Re-exports"),
4349+
ItemType::Module => ("modules", "Modules"),
4350+
ItemType::Struct => ("structs", "Structs"),
4351+
ItemType::Union => ("unions", "Unions"),
4352+
ItemType::Enum => ("enums", "Enums"),
4353+
ItemType::Function => ("functions", "Functions"),
4354+
ItemType::Typedef => ("types", "Type Definitions"),
4355+
ItemType::Static => ("statics", "Statics"),
4356+
ItemType::Constant => ("constants", "Constants"),
4357+
ItemType::Trait => ("traits", "Traits"),
4358+
ItemType::Impl => ("impls", "Implementations"),
4359+
ItemType::TyMethod => ("tymethods", "Type Methods"),
4360+
ItemType::Method => ("methods", "Methods"),
4361+
ItemType::StructField => ("fields", "Struct Fields"),
4362+
ItemType::Variant => ("variants", "Variants"),
4363+
ItemType::Macro => ("macros", "Macros"),
4364+
ItemType::Primitive => ("primitives", "Primitive Types"),
4365+
ItemType::AssociatedType => ("associated-types", "Associated Types"),
4366+
ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
4367+
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
4368+
ItemType::Keyword => ("keywords", "Keywords"),
4369+
}
4370+
}
4371+
43634372
fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
43644373
items: &[clean::Item]) -> fmt::Result {
43654374
let mut sidebar = String::new();
@@ -4379,29 +4388,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
43794388
ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
43804389
ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
43814390
if items.iter().any(|it| !it.is_stripped() && it.type_() == myty) {
4382-
let (short, name) = match myty {
4383-
ItemType::ExternCrate |
4384-
ItemType::Import => ("reexports", "Re-exports"),
4385-
ItemType::Module => ("modules", "Modules"),
4386-
ItemType::Struct => ("structs", "Structs"),
4387-
ItemType::Union => ("unions", "Unions"),
4388-
ItemType::Enum => ("enums", "Enums"),
4389-
ItemType::Function => ("functions", "Functions"),
4390-
ItemType::Typedef => ("types", "Type Definitions"),
4391-
ItemType::Static => ("statics", "Statics"),
4392-
ItemType::Constant => ("constants", "Constants"),
4393-
ItemType::Trait => ("traits", "Traits"),
4394-
ItemType::Impl => ("impls", "Implementations"),
4395-
ItemType::TyMethod => ("tymethods", "Type Methods"),
4396-
ItemType::Method => ("methods", "Methods"),
4397-
ItemType::StructField => ("fields", "Struct Fields"),
4398-
ItemType::Variant => ("variants", "Variants"),
4399-
ItemType::Macro => ("macros", "Macros"),
4400-
ItemType::Primitive => ("primitives", "Primitive Types"),
4401-
ItemType::AssociatedType => ("associated-types", "Associated Types"),
4402-
ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
4403-
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
4404-
};
4391+
let (short, name) = item_ty_to_strs(&myty);
44054392
sidebar.push_str(&format!("<li><a href=\"#{id}\">{name}</a></li>",
44064393
id = short,
44074394
name = name));
@@ -4462,6 +4449,13 @@ fn item_primitive(w: &mut fmt::Formatter, cx: &Context,
44624449
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
44634450
}
44644451

4452+
fn item_keyword(w: &mut fmt::Formatter, cx: &Context,
4453+
it: &clean::Item,
4454+
_p: &str) -> fmt::Result {
4455+
document(w, cx, it)?;
4456+
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
4457+
}
4458+
44654459
const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang";
44664460

44674461
fn make_item_keywords(it: &clean::Item) -> String {

src/librustdoc/html/static/main.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
"constant",
3939
"associatedconstant",
4040
"union",
41-
"foreigntype"];
41+
"foreigntype",
42+
"keyword"];
4243

4344
var search_input = document.getElementsByClassName('search-input')[0];
4445

@@ -158,6 +159,7 @@
158159

159160
// used for special search precedence
160161
var TY_PRIMITIVE = itemTypes.indexOf("primitive");
162+
var TY_KEYWORD = itemTypes.indexOf("keyword");
161163

162164
onEach(document.getElementsByClassName('js-only'), function(e) {
163165
removeClass(e, 'js-only');
@@ -530,11 +532,13 @@
530532
b = bbb.index;
531533
if (a !== b) { return a - b; }
532534

533-
// special precedence for primitive pages
534-
if ((aaa.item.ty === TY_PRIMITIVE) && (bbb.item.ty !== TY_PRIMITIVE)) {
535+
// special precedence for primitive and keyword pages
536+
if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
537+
(aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
535538
return -1;
536539
}
537-
if ((bbb.item.ty === TY_PRIMITIVE) && (aaa.item.ty !== TY_PRIMITIVE)) {
540+
if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
541+
(bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
538542
return 1;
539543
}
540544

@@ -1206,7 +1210,7 @@
12061210
displayPath = item.path + '::';
12071211
href = rootPath + item.path.replace(/::/g, '/') + '/' +
12081212
name + '/index.html';
1209-
} else if (type === "primitive") {
1213+
} else if (type === "primitive" || type === "keyword") {
12101214
displayPath = "";
12111215
href = rootPath + item.path.replace(/::/g, '/') +
12121216
'/' + type + '.' + name + '.html';
@@ -1700,6 +1704,7 @@
17001704
block("fn", "Functions");
17011705
block("type", "Type Definitions");
17021706
block("foreigntype", "Foreign Types");
1707+
block("keyword", "Keywords");
17031708
}
17041709

17051710
window.initSidebarItems = initSidebarItems;

src/librustdoc/html/static/rustdoc.css

+5
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,11 @@ tr.result span.primitive::after {
628628
font-style: italic;
629629
}
630630

631+
tr.result span.keyword::after {
632+
content: ' (keyword)';
633+
font-style: italic;
634+
}
635+
631636
body.blur > :not(#help) {
632637
filter: blur(8px);
633638
-webkit-filter: blur(8px);

0 commit comments

Comments
 (0)