mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Add new doc(attribute = "...") attribute
This commit is contained in:
@@ -188,6 +188,7 @@ macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) =
|
||||
notable_trait => doc_notable_trait
|
||||
}
|
||||
"meant for internal use only" {
|
||||
attribute => rustdoc_internals
|
||||
keyword => rustdoc_internals
|
||||
fake_variadic => rustdoc_internals
|
||||
search_unbox => rustdoc_internals
|
||||
|
||||
@@ -145,6 +145,10 @@ passes_doc_alias_start_end =
|
||||
passes_doc_attr_not_crate_level =
|
||||
`#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
|
||||
|
||||
passes_doc_attribute_not_attribute =
|
||||
nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]`
|
||||
.help = only existing builtin attributes are allowed in core/std
|
||||
|
||||
passes_doc_cfg_hide_takes_list =
|
||||
`#[doc(cfg_hide(...))]` takes a list of attributes
|
||||
|
||||
@@ -173,16 +177,16 @@ passes_doc_inline_only_use =
|
||||
passes_doc_invalid =
|
||||
invalid `doc` attribute
|
||||
|
||||
passes_doc_keyword_empty_mod =
|
||||
`#[doc(keyword = "...")]` should be used on empty modules
|
||||
passes_doc_keyword_attribute_empty_mod =
|
||||
`#[doc({$attr_name} = "...")]` should be used on empty modules
|
||||
|
||||
passes_doc_keyword_attribute_not_mod =
|
||||
`#[doc({$attr_name} = "...")]` should be used on modules
|
||||
|
||||
passes_doc_keyword_not_keyword =
|
||||
nonexistent keyword `{$keyword}` used in `#[doc(keyword = "...")]`
|
||||
.help = only existing keywords are allowed in core/std
|
||||
|
||||
passes_doc_keyword_not_mod =
|
||||
`#[doc(keyword = "...")]` should be used on modules
|
||||
|
||||
passes_doc_keyword_only_impl =
|
||||
`#[doc(keyword = "...")]` should be used on impl blocks
|
||||
|
||||
|
||||
@@ -851,7 +851,12 @@ fn check_doc_alias(
|
||||
}
|
||||
}
|
||||
|
||||
fn check_doc_keyword(&self, meta: &MetaItemInner, hir_id: HirId) {
|
||||
fn check_doc_keyword_and_attribute(
|
||||
&self,
|
||||
meta: &MetaItemInner,
|
||||
hir_id: HirId,
|
||||
is_keyword: bool,
|
||||
) {
|
||||
fn is_doc_keyword(s: Symbol) -> bool {
|
||||
// FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we
|
||||
// can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the
|
||||
@@ -859,9 +864,17 @@ fn is_doc_keyword(s: Symbol) -> bool {
|
||||
s.is_reserved(|| edition::LATEST_STABLE_EDITION) || s.is_weak() || s == sym::SelfTy
|
||||
}
|
||||
|
||||
let doc_keyword = match meta.value_str() {
|
||||
fn is_builtin_attr(s: Symbol) -> bool {
|
||||
rustc_feature::BUILTIN_ATTRIBUTE_MAP.contains_key(&s)
|
||||
}
|
||||
|
||||
fn get_attr_name(is_keyword: bool) -> &'static str {
|
||||
if is_keyword { "keyword" } else { "attribute" }
|
||||
}
|
||||
|
||||
let value = match meta.value_str() {
|
||||
Some(value) if value != sym::empty => value,
|
||||
_ => return self.doc_attr_str_error(meta, "keyword"),
|
||||
_ => return self.doc_attr_str_error(meta, get_attr_name(is_keyword)),
|
||||
};
|
||||
|
||||
let item_kind = match self.tcx.hir_node(hir_id) {
|
||||
@@ -871,19 +884,32 @@ fn is_doc_keyword(s: Symbol) -> bool {
|
||||
match item_kind {
|
||||
Some(ItemKind::Mod(_, module)) => {
|
||||
if !module.item_ids.is_empty() {
|
||||
self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() });
|
||||
self.dcx().emit_err(errors::DocKeywordAttributeEmptyMod {
|
||||
span: meta.span(),
|
||||
attr_name: get_attr_name(is_keyword),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::DocKeywordNotMod { span: meta.span() });
|
||||
self.dcx().emit_err(errors::DocKeywordAttributeNotMod {
|
||||
span: meta.span(),
|
||||
attr_name: get_attr_name(is_keyword),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
if !is_doc_keyword(doc_keyword) {
|
||||
self.dcx().emit_err(errors::DocKeywordNotKeyword {
|
||||
if is_keyword {
|
||||
if !is_doc_keyword(value) {
|
||||
self.dcx().emit_err(errors::DocKeywordNotKeyword {
|
||||
span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
|
||||
keyword: value,
|
||||
});
|
||||
}
|
||||
} else if !is_builtin_attr(value) {
|
||||
self.dcx().emit_err(errors::DocAttributeNotAttribute {
|
||||
span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
|
||||
keyword: doc_keyword,
|
||||
attribute: value,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1144,7 +1170,13 @@ fn check_doc_attrs(
|
||||
|
||||
Some(sym::keyword) => {
|
||||
if self.check_attr_not_crate_level(meta, hir_id, "keyword") {
|
||||
self.check_doc_keyword(meta, hir_id);
|
||||
self.check_doc_keyword_and_attribute(meta, hir_id, true);
|
||||
}
|
||||
}
|
||||
|
||||
Some(sym::attribute) => {
|
||||
if self.check_attr_not_crate_level(meta, hir_id, "attribute") {
|
||||
self.check_doc_keyword_and_attribute(meta, hir_id, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,10 +195,11 @@ pub(crate) struct DocAliasMalformed {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_doc_keyword_empty_mod)]
|
||||
pub(crate) struct DocKeywordEmptyMod {
|
||||
#[diag(passes_doc_keyword_attribute_empty_mod)]
|
||||
pub(crate) struct DocKeywordAttributeEmptyMod {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub attr_name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@@ -211,10 +212,20 @@ pub(crate) struct DocKeywordNotKeyword {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_doc_keyword_not_mod)]
|
||||
pub(crate) struct DocKeywordNotMod {
|
||||
#[diag(passes_doc_attribute_not_attribute)]
|
||||
#[help]
|
||||
pub(crate) struct DocAttributeNotAttribute {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub attribute: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_doc_keyword_attribute_not_mod)]
|
||||
pub(crate) struct DocKeywordAttributeNotMod {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub attr_name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
||||
@@ -5016,7 +5016,7 @@ fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExport
|
||||
}
|
||||
ResolveDocLinks::Exported
|
||||
if !maybe_exported.eval(self.r)
|
||||
&& !rustdoc::has_primitive_or_keyword_docs(attrs) =>
|
||||
&& !rustdoc::has_primitive_or_keyword_or_attribute_docs(attrs) =>
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -373,8 +373,8 @@ pub fn inner_docs(attrs: &[impl AttributeExt]) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]`.
|
||||
pub fn has_primitive_or_keyword_docs(attrs: &[impl AttributeExt]) -> bool {
|
||||
/// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]` or `#[doc(attribute)]`.
|
||||
pub fn has_primitive_or_keyword_or_attribute_docs(attrs: &[impl AttributeExt]) -> bool {
|
||||
for attr in attrs {
|
||||
if attr.has_name(sym::rustc_doc_primitive) {
|
||||
return true;
|
||||
@@ -382,7 +382,7 @@ pub fn has_primitive_or_keyword_docs(attrs: &[impl AttributeExt]) -> bool {
|
||||
&& let Some(items) = attr.meta_item_list()
|
||||
{
|
||||
for item in items {
|
||||
if item.has_name(sym::keyword) {
|
||||
if item.has_name(sym::keyword) || item.has_name(sym::attribute) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,6 +540,7 @@
|
||||
att_syntax,
|
||||
attr,
|
||||
attr_literals,
|
||||
attribute,
|
||||
attributes,
|
||||
audit_that,
|
||||
augmented_assignments,
|
||||
|
||||
@@ -226,15 +226,28 @@ fn mapped_root_modules<T>(
|
||||
}
|
||||
|
||||
pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> {
|
||||
fn as_keyword(did: DefId, tcx: TyCtxt<'_>) -> Option<(DefId, Symbol)> {
|
||||
self.retrieve_keywords_or_documented_attributes(tcx, sym::keyword)
|
||||
}
|
||||
pub(crate) fn documented_attributes(
|
||||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
) -> impl Iterator<Item = (DefId, Symbol)> {
|
||||
self.retrieve_keywords_or_documented_attributes(tcx, sym::attribute)
|
||||
}
|
||||
|
||||
fn retrieve_keywords_or_documented_attributes(
|
||||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
name: Symbol,
|
||||
) -> impl Iterator<Item = (DefId, Symbol)> {
|
||||
let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> {
|
||||
tcx.get_attrs(did, sym::doc)
|
||||
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
|
||||
.filter(|meta| meta.has_name(sym::keyword))
|
||||
.filter(|meta| meta.has_name(name))
|
||||
.find_map(|meta| meta.value_str())
|
||||
.map(|value| (did, value))
|
||||
}
|
||||
|
||||
self.mapped_root_modules(tcx, as_keyword)
|
||||
};
|
||||
self.mapped_root_modules(tcx, as_target)
|
||||
}
|
||||
|
||||
pub(crate) fn primitives(
|
||||
@@ -592,6 +605,9 @@ pub(crate) fn is_extern_crate(&self) -> bool {
|
||||
pub(crate) fn is_keyword(&self) -> bool {
|
||||
self.type_() == ItemType::Keyword
|
||||
}
|
||||
pub(crate) fn is_attribute(&self) -> bool {
|
||||
self.type_() == ItemType::Attribute
|
||||
}
|
||||
pub(crate) fn is_stripped(&self) -> bool {
|
||||
match self.kind {
|
||||
StrippedItem(..) => true,
|
||||
@@ -735,7 +751,9 @@ pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
|
||||
// Primitives and Keywords are written in the source code as private modules.
|
||||
// The modules need to be private so that nobody actually uses them, but the
|
||||
// keywords and primitives that they are documenting are public.
|
||||
ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public),
|
||||
ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
|
||||
return Some(Visibility::Public);
|
||||
}
|
||||
// Variant fields inherit their enum's visibility.
|
||||
StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
|
||||
return None;
|
||||
@@ -942,7 +960,12 @@ pub(crate) enum ItemKind {
|
||||
AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
|
||||
/// An item that has been stripped by a rustdoc pass
|
||||
StrippedItem(Box<ItemKind>),
|
||||
/// This item represents a module with a `#[doc(keyword = "...")]` attribute which is used
|
||||
/// to generate documentation for Rust keywords.
|
||||
KeywordItem,
|
||||
/// This item represents a module with a `#[doc(attribute = "...")]` attribute which is used
|
||||
/// to generate documentation for Rust builtin attributes.
|
||||
AttributeItem,
|
||||
}
|
||||
|
||||
impl ItemKind {
|
||||
@@ -983,7 +1006,8 @@ pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
|
||||
| RequiredAssocTypeItem(..)
|
||||
| AssocTypeItem(..)
|
||||
| StrippedItem(_)
|
||||
| KeywordItem => [].iter(),
|
||||
| KeywordItem
|
||||
| AttributeItem => [].iter(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
|
||||
let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
|
||||
let primitives = local_crate.primitives(cx.tcx);
|
||||
let keywords = local_crate.keywords(cx.tcx);
|
||||
let documented_attributes = local_crate.documented_attributes(cx.tcx);
|
||||
{
|
||||
let ItemKind::ModuleItem(m) = &mut module.inner.kind else { unreachable!() };
|
||||
m.items.extend(primitives.map(|(def_id, prim)| {
|
||||
@@ -73,6 +74,9 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
|
||||
m.items.extend(keywords.map(|(def_id, kw)| {
|
||||
Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem, cx)
|
||||
}));
|
||||
m.items.extend(documented_attributes.into_iter().map(|(def_id, kw)| {
|
||||
Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::AttributeItem, cx)
|
||||
}));
|
||||
}
|
||||
|
||||
Crate { module, external_traits: Box::new(mem::take(&mut cx.external_traits)) }
|
||||
|
||||
@@ -96,7 +96,8 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
|
||||
| ImplAssocConstItem(..)
|
||||
| RequiredAssocTypeItem(..)
|
||||
| AssocTypeItem(..)
|
||||
| KeywordItem => kind,
|
||||
| KeywordItem
|
||||
| AttributeItem => kind,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -372,7 +372,8 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
|
||||
| clean::RequiredAssocTypeItem(..)
|
||||
| clean::AssocTypeItem(..)
|
||||
| clean::StrippedItem(..)
|
||||
| clean::KeywordItem => {
|
||||
| clean::KeywordItem
|
||||
| clean::AttributeItem => {
|
||||
// FIXME: Do these need handling?
|
||||
// The person writing this comment doesn't know.
|
||||
// So would rather leave them to an expert,
|
||||
|
||||
@@ -57,6 +57,7 @@ pub(crate) enum ItemType {
|
||||
TraitAlias = 25,
|
||||
// This number is reserved for use in JavaScript
|
||||
// Generic = 26,
|
||||
Attribute = 27,
|
||||
}
|
||||
|
||||
impl Serialize for ItemType {
|
||||
@@ -148,6 +149,7 @@ fn from(item: &'a clean::Item) -> ItemType {
|
||||
clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType,
|
||||
clean::ForeignTypeItem => ItemType::ForeignType,
|
||||
clean::KeywordItem => ItemType::Keyword,
|
||||
clean::AttributeItem => ItemType::Attribute,
|
||||
clean::TraitAliasItem(..) => ItemType::TraitAlias,
|
||||
clean::ProcMacroItem(mac) => match mac.kind {
|
||||
MacroKind::Bang => ItemType::Macro,
|
||||
@@ -236,6 +238,7 @@ pub(crate) fn as_str(&self) -> &'static str {
|
||||
ItemType::ProcAttribute => "attr",
|
||||
ItemType::ProcDerive => "derive",
|
||||
ItemType::TraitAlias => "traitalias",
|
||||
ItemType::Attribute => "attribute",
|
||||
}
|
||||
}
|
||||
pub(crate) fn is_method(&self) -> bool {
|
||||
|
||||
@@ -218,7 +218,7 @@ fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
|
||||
} else {
|
||||
it.name.as_ref().unwrap().as_str()
|
||||
};
|
||||
if !it.is_primitive() && !it.is_keyword() {
|
||||
if !it.is_primitive() && !it.is_keyword() && !it.is_attribute() {
|
||||
if !is_module {
|
||||
title.push_str(" in ");
|
||||
}
|
||||
|
||||
@@ -2535,6 +2535,7 @@ pub(crate) enum ItemSection {
|
||||
AssociatedConstants,
|
||||
ForeignTypes,
|
||||
Keywords,
|
||||
Attributes,
|
||||
AttributeMacros,
|
||||
DeriveMacros,
|
||||
TraitAliases,
|
||||
@@ -2567,6 +2568,7 @@ impl ItemSection {
|
||||
AssociatedConstants,
|
||||
ForeignTypes,
|
||||
Keywords,
|
||||
Attributes,
|
||||
AttributeMacros,
|
||||
DeriveMacros,
|
||||
TraitAliases,
|
||||
@@ -2596,6 +2598,7 @@ fn id(self) -> &'static str {
|
||||
Self::AssociatedConstants => "associated-consts",
|
||||
Self::ForeignTypes => "foreign-types",
|
||||
Self::Keywords => "keywords",
|
||||
Self::Attributes => "attributes",
|
||||
Self::AttributeMacros => "attributes",
|
||||
Self::DeriveMacros => "derives",
|
||||
Self::TraitAliases => "trait-aliases",
|
||||
@@ -2625,6 +2628,7 @@ fn name(self) -> &'static str {
|
||||
Self::AssociatedConstants => "Associated Constants",
|
||||
Self::ForeignTypes => "Foreign Types",
|
||||
Self::Keywords => "Keywords",
|
||||
Self::Attributes => "Attributes",
|
||||
Self::AttributeMacros => "Attribute Macros",
|
||||
Self::DeriveMacros => "Derive Macros",
|
||||
Self::TraitAliases => "Trait Aliases",
|
||||
@@ -2655,6 +2659,7 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection {
|
||||
ItemType::AssocConst => ItemSection::AssociatedConstants,
|
||||
ItemType::ForeignType => ItemSection::ForeignTypes,
|
||||
ItemType::Keyword => ItemSection::Keywords,
|
||||
ItemType::Attribute => ItemSection::Attributes,
|
||||
ItemType::ProcAttribute => ItemSection::AttributeMacros,
|
||||
ItemType::ProcDerive => ItemSection::DeriveMacros,
|
||||
ItemType::TraitAlias => ItemSection::TraitAliases,
|
||||
|
||||
@@ -173,6 +173,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
|
||||
clean::ConstantItem(..) => "Constant ",
|
||||
clean::ForeignTypeItem => "Foreign Type ",
|
||||
clean::KeywordItem => "Keyword ",
|
||||
clean::AttributeItem => "Attribute ",
|
||||
clean::TraitAliasItem(..) => "Trait Alias ",
|
||||
_ => {
|
||||
// We don't generate pages for any other type.
|
||||
@@ -193,7 +194,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
|
||||
let src_href =
|
||||
if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
|
||||
|
||||
let path_components = if item.is_primitive() || item.is_keyword() {
|
||||
let path_components = if item.is_primitive() || item.is_keyword() || item.is_attribute() {
|
||||
vec![]
|
||||
} else {
|
||||
let cur = &cx.current;
|
||||
@@ -252,7 +253,9 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
|
||||
clean::ForeignTypeItem => {
|
||||
write!(buf, "{}", item_foreign_type(cx, item))
|
||||
}
|
||||
clean::KeywordItem => write!(buf, "{}", item_keyword(cx, item)),
|
||||
clean::KeywordItem | clean::AttributeItem => {
|
||||
write!(buf, "{}", item_keyword_or_attribute(cx, item))
|
||||
}
|
||||
clean::TraitAliasItem(ta) => {
|
||||
write!(buf, "{}", item_trait_alias(cx, item, ta))
|
||||
}
|
||||
@@ -2151,7 +2154,7 @@ fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
|
||||
})
|
||||
}
|
||||
|
||||
fn item_keyword(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
|
||||
fn item_keyword_or_attribute(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
|
||||
document(cx, it, None, HeadingOffset::H2)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ nav.sub {
|
||||
--function-link-color: #ad7c37;
|
||||
--macro-link-color: #068000;
|
||||
--keyword-link-color: #3873ad;
|
||||
--attribute-link-color: #3873ad;
|
||||
--mod-link-color: #3873ad;
|
||||
--link-color: #3873ad;
|
||||
--sidebar-link-color: #356da4;
|
||||
@@ -180,6 +181,7 @@ nav.sub {
|
||||
--function-link-color: #2bab63;
|
||||
--macro-link-color: #09bd00;
|
||||
--keyword-link-color: #d2991d;
|
||||
--attribute-link-color: #d2991d;
|
||||
--mod-link-color: #d2991d;
|
||||
--link-color: #d2991d;
|
||||
--sidebar-link-color: #fdbf35;
|
||||
|
||||
@@ -400,6 +400,10 @@ span.keyword, a.keyword {
|
||||
color: var(--keyword-link-color);
|
||||
}
|
||||
|
||||
span.attribute, a.attribute {
|
||||
color: var(--attribute-link-color);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
@@ -3190,6 +3194,7 @@ by default.
|
||||
--function-link-color: #ad7c37;
|
||||
--macro-link-color: #068000;
|
||||
--keyword-link-color: #3873ad;
|
||||
--attribute-link-color: #3873ad;
|
||||
--mod-link-color: #3873ad;
|
||||
--link-color: #3873ad;
|
||||
--sidebar-link-color: #356da4;
|
||||
@@ -3294,6 +3299,7 @@ by default.
|
||||
--function-link-color: #2bab63;
|
||||
--macro-link-color: #09bd00;
|
||||
--keyword-link-color: #d2991d;
|
||||
--attribute-link-color: #d2991d;
|
||||
--mod-link-color: #d2991d;
|
||||
--link-color: #d2991d;
|
||||
--sidebar-link-color: #fdbf35;
|
||||
@@ -3407,6 +3413,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
||||
--function-link-color: #fdd687;
|
||||
--macro-link-color: #a37acc;
|
||||
--keyword-link-color: #39afd7;
|
||||
--attribute-link-color: #39afd7;
|
||||
--mod-link-color: #39afd7;
|
||||
--link-color: #39afd7;
|
||||
--sidebar-link-color: #53b1db;
|
||||
|
||||
@@ -790,6 +790,7 @@ function preLoadCss(cssUrl) {
|
||||
//block("associatedconstant", "associated-consts", "Associated Constants");
|
||||
block("foreigntype", "foreign-types", "Foreign Types");
|
||||
block("keyword", "keywords", "Keywords");
|
||||
block("attribute", "attributes", "Attributes");
|
||||
block("attr", "attributes", "Attribute Macros");
|
||||
block("derive", "derives", "Derive Macros");
|
||||
block("traitalias", "trait-aliases", "Trait Aliases");
|
||||
|
||||
@@ -119,6 +119,7 @@ const itemTypes = [
|
||||
"derive",
|
||||
"traitalias", // 25
|
||||
"generic",
|
||||
"attribute",
|
||||
];
|
||||
|
||||
// used for special search precedence
|
||||
@@ -2058,7 +2059,7 @@ class DocSearch {
|
||||
displayPath = item.modulePath + "::";
|
||||
href = this.rootPath + item.modulePath.replace(/::/g, "/") +
|
||||
"/index.html#reexport." + name;
|
||||
} else if (type === "primitive" || type === "keyword") {
|
||||
} else if (type === "primitive" || type === "keyword" || type === "attribute") {
|
||||
displayPath = "";
|
||||
exactPath = "";
|
||||
href = this.rootPath + path.replace(/::/g, "/") +
|
||||
@@ -4560,6 +4561,8 @@ const longItemTypes = [
|
||||
"attribute macro",
|
||||
"derive macro",
|
||||
"trait alias",
|
||||
"",
|
||||
"attribute",
|
||||
];
|
||||
// @ts-expect-error
|
||||
let currentResults;
|
||||
|
||||
@@ -52,7 +52,7 @@ pub(super) fn convert_item(&self, item: &clean::Item) -> Option<Item> {
|
||||
let clean::ItemInner { name, item_id, .. } = *item.inner;
|
||||
let id = self.id_from_item(item);
|
||||
let inner = match item.kind {
|
||||
clean::KeywordItem => return None,
|
||||
clean::KeywordItem | clean::AttributeItem => return None,
|
||||
clean::StrippedItem(ref inner) => {
|
||||
match &**inner {
|
||||
// We document stripped modules as with `Module::is_stripped` set to
|
||||
@@ -85,7 +85,7 @@ pub(super) fn convert_item(&self, item: &clean::Item) -> Option<Item> {
|
||||
fn ids(&self, items: &[clean::Item]) -> Vec<Id> {
|
||||
items
|
||||
.iter()
|
||||
.filter(|i| !i.is_stripped() && !i.is_keyword())
|
||||
.filter(|i| !i.is_stripped() && !i.is_keyword() && !i.is_attribute())
|
||||
.map(|i| self.id_from_item(i))
|
||||
.collect()
|
||||
}
|
||||
@@ -93,7 +93,10 @@ fn ids(&self, items: &[clean::Item]) -> Vec<Id> {
|
||||
fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> {
|
||||
items
|
||||
.iter()
|
||||
.map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(i)))
|
||||
.map(|i| {
|
||||
(!i.is_stripped() && !i.is_keyword() && !i.is_attribute())
|
||||
.then(|| self.id_from_item(i))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -332,8 +335,8 @@ fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum
|
||||
bounds: b.into_json(renderer),
|
||||
type_: Some(t.item_type.as_ref().unwrap_or(&t.type_).into_json(renderer)),
|
||||
},
|
||||
// `convert_item` early returns `None` for stripped items and keywords.
|
||||
KeywordItem => unreachable!(),
|
||||
// `convert_item` early returns `None` for stripped items, keywords and attributes.
|
||||
KeywordItem | AttributeItem => unreachable!(),
|
||||
StrippedItem(inner) => {
|
||||
match inner.as_ref() {
|
||||
ModuleItem(m) => ItemEnum::Module(Module {
|
||||
@@ -887,6 +890,7 @@ fn from_clean(kind: &ItemType, _renderer: &JsonRenderer<'_>) -> Self {
|
||||
AssocType => ItemKind::AssocType,
|
||||
ForeignType => ItemKind::ExternType,
|
||||
Keyword => ItemKind::Keyword,
|
||||
Attribute => ItemKind::Attribute,
|
||||
TraitAlias => ItemKind::TraitAlias,
|
||||
ProcAttribute => ItemKind::ProcAttribute,
|
||||
ProcDerive => ItemKind::ProcDerive,
|
||||
|
||||
@@ -67,6 +67,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
|
||||
| clean::ImportItem(_)
|
||||
| clean::PrimitiveItem(_)
|
||||
| clean::KeywordItem
|
||||
| clean::AttributeItem
|
||||
| clean::ModuleItem(_)
|
||||
| clean::TraitAliasItem(_)
|
||||
| clean::ForeignFunctionItem(..)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug, ty};
|
||||
use rustc_resolve::rustdoc::{
|
||||
MalformedGenerics, has_primitive_or_keyword_docs, prepare_to_doc_link_resolution,
|
||||
MalformedGenerics, has_primitive_or_keyword_or_attribute_docs, prepare_to_doc_link_resolution,
|
||||
source_span_for_markdown_range, strip_generics_from_path,
|
||||
};
|
||||
use rustc_session::config::CrateType;
|
||||
@@ -1073,7 +1073,7 @@ fn resolve_links(&mut self, item: &Item) {
|
||||
&& let Some(def_id) = item.item_id.as_def_id()
|
||||
&& let Some(def_id) = def_id.as_local()
|
||||
&& !self.cx.tcx.effective_visibilities(()).is_exported(def_id)
|
||||
&& !has_primitive_or_keyword_docs(&item.attrs.other_attrs)
|
||||
&& !has_primitive_or_keyword_or_attribute_docs(&item.attrs.other_attrs)
|
||||
{
|
||||
// Skip link resolution for non-exported items.
|
||||
return;
|
||||
|
||||
@@ -106,7 +106,8 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
|
||||
| ItemKind::RequiredAssocTypeItem(..)
|
||||
| ItemKind::AssocTypeItem(..)
|
||||
| ItemKind::PrimitiveItem(..)
|
||||
| ItemKind::KeywordItem => own_stability,
|
||||
| ItemKind::KeywordItem
|
||||
| ItemKind::AttributeItem => own_stability,
|
||||
|
||||
ItemKind::StrippedItem(..) => unreachable!(),
|
||||
}
|
||||
|
||||
@@ -133,6 +133,8 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||
|
||||
// Keywords are never stripped
|
||||
clean::KeywordItem => {}
|
||||
// Attributes are never stripped
|
||||
clean::AttributeItem => {}
|
||||
}
|
||||
|
||||
let fastreturn = match i.kind {
|
||||
|
||||
@@ -49,7 +49,8 @@ fn visit_inner_recur(&mut self, kind: &'a ItemKind) {
|
||||
| ImplAssocConstItem(..)
|
||||
| RequiredAssocTypeItem(..)
|
||||
| AssocTypeItem(..)
|
||||
| KeywordItem => {}
|
||||
| KeywordItem
|
||||
| AttributeItem => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
// will instead cause conflicts. See #94591 for more. (This paragraph and the "Latest feature" line
|
||||
// are deliberately not in a doc comment, because they need not be in public docs.)
|
||||
//
|
||||
// Latest feature: Add Attribute::MacroUse
|
||||
pub const FORMAT_VERSION: u32 = 55;
|
||||
// Latest feature: Add `ItemKind::Attribute`.
|
||||
pub const FORMAT_VERSION: u32 = 56;
|
||||
|
||||
/// The root of the emitted JSON blob.
|
||||
///
|
||||
@@ -552,6 +552,11 @@ pub enum ItemKind {
|
||||
/// [`Item`]s of this kind only come from the come library and exist solely
|
||||
/// to carry documentation for the respective keywords.
|
||||
Keyword,
|
||||
/// An attribute declaration.
|
||||
///
|
||||
/// [`Item`]s of this kind only come from the core library and exist solely
|
||||
/// to carry documentation for the respective builtin attributes.
|
||||
Attribute,
|
||||
}
|
||||
|
||||
/// Specific fields of an item.
|
||||
|
||||
@@ -26,6 +26,7 @@ pub(crate) enum Kind {
|
||||
AssocType,
|
||||
Primitive,
|
||||
Keyword,
|
||||
Attribute,
|
||||
// Not in ItemKind
|
||||
ProcMacro,
|
||||
}
|
||||
@@ -53,6 +54,7 @@ pub fn can_appear_in_mod(self) -> bool {
|
||||
ExternType => true,
|
||||
|
||||
// FIXME(adotinthevoid): I'm not sure if these are correct
|
||||
Attribute => false,
|
||||
Keyword => false,
|
||||
ProcAttribute => false,
|
||||
ProcDerive => false,
|
||||
@@ -109,6 +111,7 @@ pub fn can_appear_in_trait(self) -> bool {
|
||||
Kind::Primitive => false,
|
||||
Kind::Keyword => false,
|
||||
Kind::ProcMacro => false,
|
||||
Kind::Attribute => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +166,7 @@ pub fn from_summary(s: &ItemSummary) -> Self {
|
||||
match s.kind {
|
||||
ItemKind::AssocConst => AssocConst,
|
||||
ItemKind::AssocType => AssocType,
|
||||
ItemKind::Attribute => Attribute,
|
||||
ItemKind::Constant => Constant,
|
||||
ItemKind::Enum => Enum,
|
||||
ItemKind::ExternCrate => ExternCrate,
|
||||
|
||||
Reference in New Issue
Block a user