Skip to content

Commit

Permalink
Auto merge of #51140 - GuillaumeGomez:doc-keyword, r=QuietMisdreavus
Browse files Browse the repository at this point in the history
rustdoc: introduce the #[doc(keyword="")] attribute for documenting keywords

Part of #34601.

r? @QuietMisdreavus
  • Loading branch information
bors committed Jun 5, 2018
2 parents f33db06 + 2f7fa24 commit 4122885
Show file tree
Hide file tree
Showing 16 changed files with 218 additions and 66 deletions.
22 changes: 13 additions & 9 deletions src/etc/htmldocck.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,15 +346,19 @@ def check_tree_attr(tree, path, attr, pat, regexp):
def check_tree_text(tree, path, pat, regexp):
path = normalize_xpath(path)
ret = False
for e in tree.findall(path):
try:
value = flatten(e)
except KeyError:
continue
else:
ret = check_string(value, pat, regexp)
if ret:
break
try:
for e in tree.findall(path):
try:
value = flatten(e)
except KeyError:
continue
else:
ret = check_string(value, pat, regexp)
if ret:
break
except Exception as e:
print('Failed to get path "{}"'.format(path))
raise e
return ret


Expand Down
64 changes: 62 additions & 2 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use syntax::attr;
use syntax::codemap::{dummy_spanned, Spanned};
use syntax::feature_gate::UnstableFeatures;
use syntax::ptr::P;
use syntax::symbol::keywords;
use syntax::symbol::keywords::{self, Keyword};
use syntax::symbol::{Symbol, InternedString};
use syntax_pos::{self, DUMMY_SP, Pos, FileName};

Expand Down Expand Up @@ -54,6 +54,7 @@ use std::{mem, slice, vec};
use std::iter::{FromIterator, once};
use rustc_data_structures::sync::Lrc;
use std::rc::Rc;
use std::str::FromStr;
use std::cell::RefCell;
use std::sync::Arc;
use std::u32;
Expand Down Expand Up @@ -177,7 +178,7 @@ impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx>
_ => unreachable!(),
}

let ExternalCrate { name, src, primitives, .. } = LOCAL_CRATE.clean(cx);
let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
{
let m = match module.inner {
ModuleItem(ref mut m) => m,
Expand All @@ -195,6 +196,18 @@ impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx>
inner: PrimitiveItem(prim),
}
}));
m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| {
Item {
source: Span::empty(),
name: Some(kw.clone()),
attrs: attrs,
visibility: Some(Public),
stability: get_stability(cx, def_id),
deprecation: get_deprecation(cx, def_id),
def_id,
inner: KeywordItem(kw),
}
}));
}

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

impl Clean<ExternalCrate> for CrateNum {
Expand Down Expand Up @@ -286,11 +300,53 @@ impl Clean<ExternalCrate> for CrateNum {
.filter_map(as_primitive).collect()
};

let as_keyword = |def: Def| {
if let Def::Mod(def_id) = def {
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
let mut keyword = None;
for attr in attrs.lists("doc") {
if let Some(v) = attr.value_str() {
if attr.check_name("keyword") {
keyword = Keyword::from_str(&v.as_str()).ok()
.map(|x| x.name().to_string());
if keyword.is_some() {
break
}
// FIXME: should warn on unknown keywords?
}
}
}
return keyword.map(|p| (def_id, p, attrs));
}
None
};
let keywords = if root.is_local() {
cx.tcx.hir.krate().module.item_ids.iter().filter_map(|&id| {
let item = cx.tcx.hir.expect_item(id.id);
match item.node {
hir::ItemMod(_) => {
as_keyword(Def::Mod(cx.tcx.hir.local_def_id(id.id)))
}
hir::ItemUse(ref path, hir::UseKind::Single)
if item.vis == hir::Visibility::Public => {
as_keyword(path.def).map(|(_, prim, attrs)| {
(cx.tcx.hir.local_def_id(id.id), prim, attrs)
})
}
_ => None
}
}).collect()
} else {
cx.tcx.item_children(root).iter().map(|item| item.def)
.filter_map(as_keyword).collect()
};

ExternalCrate {
name: cx.tcx.crate_name(*self).to_string(),
src: krate_src,
attrs: cx.tcx.get_attrs(root).clean(cx),
primitives,
keywords,
}
}
}
Expand Down Expand Up @@ -397,6 +453,9 @@ impl Item {
pub fn is_extern_crate(&self) -> bool {
self.type_() == ItemType::ExternCrate
}
pub fn is_keyword(&self) -> bool {
self.type_() == ItemType::Keyword
}

pub fn is_stripped(&self) -> bool {
match self.inner { StrippedItem(..) => true, _ => false }
Expand Down Expand Up @@ -475,6 +534,7 @@ pub enum ItemEnum {
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
/// An item that has been stripped by a rustdoc pass
StrippedItem(Box<ItemEnum>),
KeywordItem(String),
}

impl ItemEnum {
Expand Down
8 changes: 8 additions & 0 deletions src/librustdoc/html/item_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub enum ItemType {
AssociatedConst = 18,
Union = 19,
ForeignType = 20,
Keyword = 21,
}


Expand All @@ -50,6 +51,7 @@ pub enum NameSpace {
Type,
Value,
Macro,
Keyword,
}

impl<'a> From<&'a clean::Item> for ItemType {
Expand Down Expand Up @@ -83,6 +85,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
clean::ForeignTypeItem => ItemType::ForeignType,
clean::KeywordItem(..) => ItemType::Keyword,
clean::StrippedItem(..) => unreachable!(),
}
}
Expand Down Expand Up @@ -131,6 +134,7 @@ impl ItemType {
ItemType::Constant => "constant",
ItemType::AssociatedConst => "associatedconstant",
ItemType::ForeignType => "foreigntype",
ItemType::Keyword => "keyword",
}
}

Expand Down Expand Up @@ -159,6 +163,8 @@ impl ItemType {
ItemType::AssociatedConst => NameSpace::Value,

ItemType::Macro => NameSpace::Macro,

ItemType::Keyword => NameSpace::Keyword,
}
}
}
Expand All @@ -172,13 +178,15 @@ impl fmt::Display for ItemType {
pub const NAMESPACE_TYPE: &'static str = "t";
pub const NAMESPACE_VALUE: &'static str = "v";
pub const NAMESPACE_MACRO: &'static str = "m";
pub const NAMESPACE_KEYWORD: &'static str = "k";

impl NameSpace {
pub fn to_static_str(&self) -> &'static str {
match *self {
NameSpace::Type => NAMESPACE_TYPE,
NameSpace::Value => NAMESPACE_VALUE,
NameSpace::Macro => NAMESPACE_MACRO,
NameSpace::Keyword => NAMESPACE_KEYWORD,
}
}
}
Expand Down
87 changes: 40 additions & 47 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,7 @@ struct AllTypes {
typedefs: HashSet<ItemEntry>,
statics: HashSet<ItemEntry>,
constants: HashSet<ItemEntry>,
keywords: HashSet<ItemEntry>,
}

impl AllTypes {
Expand All @@ -1556,6 +1557,7 @@ impl AllTypes {
typedefs: HashSet::with_capacity(100),
statics: HashSet::with_capacity(100),
constants: HashSet::with_capacity(100),
keywords: HashSet::with_capacity(100),
}
}

Expand Down Expand Up @@ -2063,12 +2065,13 @@ impl<'a> fmt::Display for Item<'a> {
clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
clean::ConstantItem(..) => write!(fmt, "Constant ")?,
clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?,
clean::KeywordItem(..) => write!(fmt, "Keyword ")?,
_ => {
// We don't generate pages for any other type.
unreachable!();
}
}
if !self.item.is_primitive() {
if !self.item.is_primitive() && !self.item.is_keyword() {
let cur = &self.cx.current;
let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() };
for (i, component) in cur.iter().enumerate().take(amt) {
Expand Down Expand Up @@ -2126,6 +2129,7 @@ impl<'a> fmt::Display for Item<'a> {
item_static(fmt, self.cx, self.item, i),
clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c),
clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item),
clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k),
_ => {
// We don't generate pages for any other type.
unreachable!();
Expand Down Expand Up @@ -2353,29 +2357,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
write!(w, "</table>")?;
}
curty = myty;
let (short, name) = match myty.unwrap() {
ItemType::ExternCrate |
ItemType::Import => ("reexports", "Re-exports"),
ItemType::Module => ("modules", "Modules"),
ItemType::Struct => ("structs", "Structs"),
ItemType::Union => ("unions", "Unions"),
ItemType::Enum => ("enums", "Enums"),
ItemType::Function => ("functions", "Functions"),
ItemType::Typedef => ("types", "Type Definitions"),
ItemType::Static => ("statics", "Statics"),
ItemType::Constant => ("constants", "Constants"),
ItemType::Trait => ("traits", "Traits"),
ItemType::Impl => ("impls", "Implementations"),
ItemType::TyMethod => ("tymethods", "Type Methods"),
ItemType::Method => ("methods", "Methods"),
ItemType::StructField => ("fields", "Struct Fields"),
ItemType::Variant => ("variants", "Variants"),
ItemType::Macro => ("macros", "Macros"),
ItemType::Primitive => ("primitives", "Primitive Types"),
ItemType::AssociatedType => ("associated-types", "Associated Types"),
ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
};
let (short, name) = item_ty_to_strs(&myty.unwrap());
write!(w, "<h2 id='{id}' class='section-header'>\
<a href=\"#{id}\">{name}</a></h2>\n<table>",
id = derive_id(short.to_owned()), name = name)?;
Expand Down Expand Up @@ -4360,6 +4342,33 @@ fn sidebar_enum(fmt: &mut fmt::Formatter, it: &clean::Item,
Ok(())
}

fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) {
match *ty {
ItemType::ExternCrate |
ItemType::Import => ("reexports", "Re-exports"),
ItemType::Module => ("modules", "Modules"),
ItemType::Struct => ("structs", "Structs"),
ItemType::Union => ("unions", "Unions"),
ItemType::Enum => ("enums", "Enums"),
ItemType::Function => ("functions", "Functions"),
ItemType::Typedef => ("types", "Type Definitions"),
ItemType::Static => ("statics", "Statics"),
ItemType::Constant => ("constants", "Constants"),
ItemType::Trait => ("traits", "Traits"),
ItemType::Impl => ("impls", "Implementations"),
ItemType::TyMethod => ("tymethods", "Type Methods"),
ItemType::Method => ("methods", "Methods"),
ItemType::StructField => ("fields", "Struct Fields"),
ItemType::Variant => ("variants", "Variants"),
ItemType::Macro => ("macros", "Macros"),
ItemType::Primitive => ("primitives", "Primitive Types"),
ItemType::AssociatedType => ("associated-types", "Associated Types"),
ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
ItemType::Keyword => ("keywords", "Keywords"),
}
}

fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
items: &[clean::Item]) -> fmt::Result {
let mut sidebar = String::new();
Expand All @@ -4379,29 +4388,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
if items.iter().any(|it| !it.is_stripped() && it.type_() == myty) {
let (short, name) = match myty {
ItemType::ExternCrate |
ItemType::Import => ("reexports", "Re-exports"),
ItemType::Module => ("modules", "Modules"),
ItemType::Struct => ("structs", "Structs"),
ItemType::Union => ("unions", "Unions"),
ItemType::Enum => ("enums", "Enums"),
ItemType::Function => ("functions", "Functions"),
ItemType::Typedef => ("types", "Type Definitions"),
ItemType::Static => ("statics", "Statics"),
ItemType::Constant => ("constants", "Constants"),
ItemType::Trait => ("traits", "Traits"),
ItemType::Impl => ("impls", "Implementations"),
ItemType::TyMethod => ("tymethods", "Type Methods"),
ItemType::Method => ("methods", "Methods"),
ItemType::StructField => ("fields", "Struct Fields"),
ItemType::Variant => ("variants", "Variants"),
ItemType::Macro => ("macros", "Macros"),
ItemType::Primitive => ("primitives", "Primitive Types"),
ItemType::AssociatedType => ("associated-types", "Associated Types"),
ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
};
let (short, name) = item_ty_to_strs(&myty);
sidebar.push_str(&format!("<li><a href=\"#{id}\">{name}</a></li>",
id = short,
name = name));
Expand Down Expand Up @@ -4462,6 +4449,12 @@ fn item_primitive(w: &mut fmt::Formatter, cx: &Context,
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
}

fn item_keyword(w: &mut fmt::Formatter, cx: &Context,
it: &clean::Item,
_p: &str) -> fmt::Result {
document(w, cx, it)
}

const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang";

fn make_item_keywords(it: &clean::Item) -> String {
Expand Down
Loading

0 comments on commit 4122885

Please sign in to comment.