From d024d6a51e05f0fa03d954d69f2863519922e00c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 28 May 2018 21:29:02 +0200 Subject: [PATCH 1/8] slightly improve rustdoc xml path error --- src/etc/htmldocck.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 8a11c6f7cfc4c..569788fe9c08a 100644 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -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 From ebee483e248d11b88839db70d41c376c4f51b276 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 28 May 2018 21:30:01 +0200 Subject: [PATCH 2/8] Add doc keyword support --- src/librustdoc/clean/mod.rs | 65 ++++++++++++++- src/librustdoc/html/item_type.rs | 8 ++ src/librustdoc/html/render.rs | 88 ++++++++++----------- src/librustdoc/html/static/main.js | 15 ++-- src/librustdoc/html/static/rustdoc.css | 5 ++ src/librustdoc/html/static/themes/dark.css | 4 +- src/librustdoc/html/static/themes/light.css | 4 +- src/librustdoc/passes/mod.rs | 3 + src/libsyntax_pos/symbol.rs | 11 +++ src/test/rustdoc/keyword.rs | 19 +++++ 10 files changed, 166 insertions(+), 56 deletions(-) create mode 100644 src/test/rustdoc/keyword.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1c1ba208678ed..ab03fe302b4a3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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}; @@ -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; @@ -177,7 +178,7 @@ impl<'a, 'tcx, 'rcx> Clean 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, @@ -195,6 +196,18 @@ impl<'a, 'tcx, 'rcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx> inner: PrimitiveItem(prim), } })); + m.items.extend(keywords.iter().map(|&(def_id, ref kw, ref attrs)| { + Item { + source: Span::empty(), + name: Some(kw.clone()), + attrs: attrs.clone(), + visibility: Some(Public), + stability: get_stability(cx, def_id), + deprecation: get_deprecation(cx, def_id), + def_id, + inner: KeywordItem(kw.clone()), + } + })); } let mut access_levels = cx.access_levels.borrow_mut(); @@ -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 for CrateNum { @@ -286,11 +300,54 @@ impl Clean 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)| { + // Pretend the primitive is local. + (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, } } } @@ -397,6 +454,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 } @@ -475,6 +535,7 @@ pub enum ItemEnum { AssociatedTypeItem(Vec, Option), /// An item that has been stripped by a rustdoc pass StrippedItem(Box), + KeywordItem(String), } impl ItemEnum { diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 537828de2c7f3..9b8ada1f6e6b2 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -42,6 +42,7 @@ pub enum ItemType { AssociatedConst = 18, Union = 19, ForeignType = 20, + Keyword = 21, } @@ -50,6 +51,7 @@ pub enum NameSpace { Type, Value, Macro, + Keyword, } impl<'a> From<&'a clean::Item> for ItemType { @@ -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!(), } } @@ -131,6 +134,7 @@ impl ItemType { ItemType::Constant => "constant", ItemType::AssociatedConst => "associatedconstant", ItemType::ForeignType => "foreigntype", + ItemType::Keyword => "keyword", } } @@ -159,6 +163,8 @@ impl ItemType { ItemType::AssociatedConst => NameSpace::Value, ItemType::Macro => NameSpace::Macro, + + ItemType::Keyword => NameSpace::Keyword, } } } @@ -172,6 +178,7 @@ 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 { @@ -179,6 +186,7 @@ impl NameSpace { NameSpace::Type => NAMESPACE_TYPE, NameSpace::Value => NAMESPACE_VALUE, NameSpace::Macro => NAMESPACE_MACRO, + NameSpace::Keyword => NAMESPACE_KEYWORD, } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 5377cd9a39143..123e6fc53ad31 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1541,6 +1541,7 @@ struct AllTypes { typedefs: HashSet, statics: HashSet, constants: HashSet, + keywords: HashSet, } impl AllTypes { @@ -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(10), } } @@ -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) { @@ -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!(); @@ -2353,29 +2357,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, write!(w, "")?; } 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, "

\ {name}

\n", id = derive_id(short.to_owned()), name = name)?; @@ -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(); @@ -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!("
  • {name}
  • ", id = short, name = name)); @@ -4462,6 +4449,13 @@ 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)?; + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) +} + const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang"; fn make_item_keywords(it: &clean::Item) -> String { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 0c937759120ef..983da51779ca2 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -38,7 +38,8 @@ "constant", "associatedconstant", "union", - "foreigntype"]; + "foreigntype", + "keyword"]; var search_input = document.getElementsByClassName('search-input')[0]; @@ -158,6 +159,7 @@ // used for special search precedence var TY_PRIMITIVE = itemTypes.indexOf("primitive"); + var TY_KEYWORD = itemTypes.indexOf("keyword"); onEach(document.getElementsByClassName('js-only'), function(e) { removeClass(e, 'js-only'); @@ -530,11 +532,13 @@ b = bbb.index; if (a !== b) { return a - b; } - // special precedence for primitive pages - if ((aaa.item.ty === TY_PRIMITIVE) && (bbb.item.ty !== TY_PRIMITIVE)) { + // special precedence for primitive and keyword pages + if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) || + (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) { return -1; } - if ((bbb.item.ty === TY_PRIMITIVE) && (aaa.item.ty !== TY_PRIMITIVE)) { + if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) || + (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) { return 1; } @@ -1206,7 +1210,7 @@ displayPath = item.path + '::'; href = rootPath + item.path.replace(/::/g, '/') + '/' + name + '/index.html'; - } else if (type === "primitive") { + } else if (type === "primitive" || type === "keyword") { displayPath = ""; href = rootPath + item.path.replace(/::/g, '/') + '/' + type + '.' + name + '.html'; @@ -1700,6 +1704,7 @@ block("fn", "Functions"); block("type", "Type Definitions"); block("foreigntype", "Foreign Types"); + block("keyword", "Keywords"); } window.initSidebarItems = initSidebarItems; diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 773b8174e56bc..d684db152df01 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -628,6 +628,11 @@ tr.result span.primitive::after { font-style: italic; } +tr.result span.keyword::after { + content: ' (keyword)'; + font-style: italic; +} + body.blur > :not(#help) { filter: blur(8px); -webkit-filter: blur(8px); diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index f96dcd9ec1c88..7add0e21f548c 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -128,6 +128,7 @@ pre { .content .highlighted.constant, .content .highlighted.static { background-color: #0063cc; } .content .highlighted.primitive { background-color: #00708a; } +.content .highlighted.keyword { background-color: #884719; } .content span.enum, .content a.enum, .block a.current.enum { color: #82b089; } .content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; } @@ -145,6 +146,7 @@ pre { .content span.method, .content a.method, .block a.current.method, .content span.tymethod, .content a.tymethod, .block a.current.tymethod, .content .fnname{ color: #2BAB63; } +.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; } pre.rust .comment { color: #8d8d8b; } pre.rust .doccomment { color: #8ca375; } @@ -209,7 +211,7 @@ a.test-arrow { color: grey; } -tr.result span.primitive::after { +tr.result span.primitive::after, tr.result span.keyword::after { color: #ddd; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 54cf50cfffd1e..7d9980363de9c 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -128,6 +128,7 @@ pre { .content .highlighted.constant, .content .highlighted.static { background-color: #c3e0ff; } .content .highlighted.primitive { background-color: #9aecff; } +.content .highlighted.keyword { background-color: #f99650; } .content span.enum, .content a.enum, .block a.current.enum { color: #508157; } .content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; } @@ -145,6 +146,7 @@ pre { .content span.method, .content a.method, .block a.current.method, .content span.tymethod, .content a.tymethod, .block a.current.tymethod, .content .fnname { color: #9a6e31; } +.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; } pre.rust .comment { color: #8E908C; } pre.rust .doccomment { color: #4D4D4C; } @@ -203,7 +205,7 @@ a.test-arrow { color: grey; } -tr.result span.primitive::after { +tr.result span.primitive::after, tr.result span.keyword::after { color: black; } diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 32f0bcada1d20..fe116a22eccbf 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -126,6 +126,9 @@ impl<'a> fold::DocFolder for Stripper<'a> { // Associated types are never stripped clean::AssociatedTypeItem(..) => {} + + // Keywords are never stripped + clean::KeywordItem(..) => {} } let fastreturn = match i.inner { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index a4b2d9de932a7..283b41e5725a9 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -311,6 +311,17 @@ macro_rules! declare_keywords {( ident: Ident::with_empty_ctxt(super::Symbol($index)) }; )* + + impl ::std::str::FromStr for Keyword { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + $($string => Ok($konst),)* + _ => Err(()), + } + } + } } impl Interner { diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs new file mode 100644 index 0000000000000..5682fce780856 --- /dev/null +++ b/src/test/rustdoc/keyword.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// @has foo/index.html '//h2[@id="keywords"]' 'Keywords' +// @has foo/index.html '//a[@href="keyword.match.html"]' 'match' +// @has foo/keyword.match.html '//a[@class="keyword"]' 'match' +// @has foo/keyword.match.html '//section[@id="main"]//div[@class="docblock"]//p' 'this is a test!' +#[doc(keyword = "match")] +/// this is a test! +mod foo{} From 904f4921f888242b7ee277f443f39a06d3f4e1c3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 29 May 2018 15:38:31 +0200 Subject: [PATCH 3/8] Few improvements --- src/librustdoc/clean/mod.rs | 7 +++---- src/librustdoc/html/render.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ab03fe302b4a3..178a85f9364de 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -196,16 +196,16 @@ impl<'a, 'tcx, 'rcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx> inner: PrimitiveItem(prim), } })); - m.items.extend(keywords.iter().map(|&(def_id, ref kw, ref attrs)| { + m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| { Item { source: Span::empty(), name: Some(kw.clone()), - attrs: attrs.clone(), + attrs: attrs, visibility: Some(Public), stability: get_stability(cx, def_id), deprecation: get_deprecation(cx, def_id), def_id, - inner: KeywordItem(kw.clone()), + inner: KeywordItem(kw), } })); } @@ -330,7 +330,6 @@ impl Clean for CrateNum { hir::ItemUse(ref path, hir::UseKind::Single) if item.vis == hir::Visibility::Public => { as_keyword(path.def).map(|(_, prim, attrs)| { - // Pretend the primitive is local. (cx.tcx.hir.local_def_id(id.id), prim, attrs) }) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 123e6fc53ad31..60178e6e7a4e0 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1557,7 +1557,7 @@ impl AllTypes { typedefs: HashSet::with_capacity(100), statics: HashSet::with_capacity(100), constants: HashSet::with_capacity(100), - keywords: HashSet::with_capacity(10), + keywords: HashSet::with_capacity(100), } } From f784d5ead29cad25c05e82e0beb9fb7586f5e462 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 2 Jun 2018 23:36:35 +0200 Subject: [PATCH 4/8] Remove useless function call for keyword generation in rustdoc --- src/librustdoc/html/render.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 60178e6e7a4e0..5c2ec2058ee9d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -4452,8 +4452,7 @@ fn item_primitive(w: &mut fmt::Formatter, cx: &Context, fn item_keyword(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, _p: &str) -> fmt::Result { - document(w, cx, it)?; - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + document(w, cx, it) } const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang"; From ded5c5a9eeb83ea7ec3c572a601afaaca6a3d9e6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 3 Jun 2018 00:45:49 +0200 Subject: [PATCH 5/8] Put doc keyword behind feature flag --- src/libstd/lib.rs | 1 + src/libsyntax/feature_gate.rs | 8 ++++++++ src/test/rustdoc/keyword.rs | 2 ++ 3 files changed, 11 insertions(+) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c576245edb755..8266cec5139f9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -316,6 +316,7 @@ #![cfg_attr(test, feature(update_panic_count))] #![cfg_attr(windows, feature(used))] #![feature(doc_alias)] +#![feature(doc_keyword)] #![feature(float_internals)] #![feature(panic_info_message)] #![cfg_attr(not(stage0), feature(panic_implementation))] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 7349745fefea1..51788b6063a33 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -476,8 +476,12 @@ declare_features! ( // 'a: { break 'a; } (active, label_break_value, "1.28.0", Some(48594), None), + // #[panic_implementation] (active, panic_implementation, "1.28.0", Some(44489), None), + + // #[doc(keyword = "...")] + (active, doc_keyword, "1.28.0", Some(51315), None), ); declare_features! ( @@ -1506,6 +1510,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, doc_alias, attr.span, "#[doc(alias = \"...\")] is experimental" ); + } else if content.iter().any(|c| c.check_name("keyword")) { + gate_feature_post!(&self, doc_keyword, attr.span, + "#[doc(keyword = \"...\")] is experimental" + ); } } } diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs index 5682fce780856..06ebf15d36457 100644 --- a/src/test/rustdoc/keyword.rs +++ b/src/test/rustdoc/keyword.rs @@ -10,6 +10,8 @@ #![crate_name = "foo"] +#![feature(doc_keyword)] + // @has foo/index.html '//h2[@id="keywords"]' 'Keywords' // @has foo/index.html '//a[@href="keyword.match.html"]' 'match' // @has foo/keyword.match.html '//a[@class="keyword"]' 'match' From 402aa0ff157d48175747812b594087deb027a151 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 3 Jun 2018 00:48:17 +0200 Subject: [PATCH 6/8] Add even more tests --- src/test/rustdoc/keyword.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs index 06ebf15d36457..b255ffddafac8 100644 --- a/src/test/rustdoc/keyword.rs +++ b/src/test/rustdoc/keyword.rs @@ -16,6 +16,9 @@ // @has foo/index.html '//a[@href="keyword.match.html"]' 'match' // @has foo/keyword.match.html '//a[@class="keyword"]' 'match' // @has foo/keyword.match.html '//section[@id="main"]//div[@class="docblock"]//p' 'this is a test!' +// @!has foo/index.html '//a/@href' 'foo/index.html' +// @!has foo/foo/index.html +// @!has-dir foo/foo #[doc(keyword = "match")] /// this is a test! mod foo{} From fb54a4afbcae8708b0158306c87cee31d7c01765 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 3 Jun 2018 12:15:55 +0200 Subject: [PATCH 7/8] Add missing ui tests --- src/test/ui/feature-gate-doc_keyword.rs | 13 +++++++++++++ src/test/ui/feature-gate-doc_keyword.stderr | 11 +++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/feature-gate-doc_keyword.rs create mode 100644 src/test/ui/feature-gate-doc_keyword.stderr diff --git a/src/test/ui/feature-gate-doc_keyword.rs b/src/test/ui/feature-gate-doc_keyword.rs new file mode 100644 index 0000000000000..2ff44626ccd06 --- /dev/null +++ b/src/test/ui/feature-gate-doc_keyword.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[doc(keyword = "match")] //~ ERROR: #[doc(keyword = "...")] is experimental +/// wonderful +mod foo{} diff --git a/src/test/ui/feature-gate-doc_keyword.stderr b/src/test/ui/feature-gate-doc_keyword.stderr new file mode 100644 index 0000000000000..e4f5109afc3eb --- /dev/null +++ b/src/test/ui/feature-gate-doc_keyword.stderr @@ -0,0 +1,11 @@ +error[E0658]: #[doc(keyword = "...")] is experimental (see issue #51315) + --> $DIR/feature-gate-doc_keyword.rs:11:1 + | +LL | #[doc(keyword = "match")] //~ ERROR: #[doc(keyword = "...")] is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(doc_keyword)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 2f7fa24aee7f7e69f9fbc37e8d2084fb1c898e97 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 Jun 2018 21:22:51 +0200 Subject: [PATCH 8/8] Update rustdoc-js --- src/tools/rustdoc-js/tester.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index bc4503903d665..a05c8a8ac9133 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -231,7 +231,9 @@ function main(argv) { finalJS = ""; var arraysToLoad = ["itemTypes"]; - var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "TY_PRIMITIVE", "levenshtein_row2"]; + var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", + "TY_PRIMITIVE", "TY_KEYWORD", + "levenshtein_row2"]; // execQuery first parameter is built in getQuery (which takes in the search input). // execQuery last parameter is built in buildIndex. // buildIndex requires the hashmap from search-index.