Skip to content

Commit c75101e

Browse files
Support new bang macro kinds in rustdoc
1 parent 91edc3e commit c75101e

File tree

11 files changed

+331
-205
lines changed

11 files changed

+331
-205
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,12 @@ pub(crate) fn try_inline(
140140
Res::Def(DefKind::Macro(kinds), did) => {
141141
let mac = build_macro(cx, did, name, kinds);
142142

143-
// FIXME: handle attributes and derives that aren't proc macros, and macros with
144-
// multiple kinds
145143
let type_kind = match kinds {
146144
MacroKinds::BANG => ItemType::Macro,
147145
MacroKinds::ATTR => ItemType::ProcAttribute,
148146
MacroKinds::DERIVE => ItemType::ProcDerive,
149-
_ => todo!("Handle macros with multiple kinds"),
147+
_ if kinds.contains(MacroKinds::BANG) => ItemType::Macro,
148+
_ => panic!("unsupported macro kind {kinds:?}"),
150149
};
151150
record_extern_fqn(cx, did, type_kind);
152151
mac
@@ -755,13 +754,14 @@ fn build_macro(
755754
macro_kinds: MacroKinds,
756755
) -> clean::ItemKind {
757756
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
758-
// FIXME: handle attributes and derives that aren't proc macros, and macros with multiple
759-
// kinds
760757
LoadedMacro::MacroDef { def, .. } => match macro_kinds {
761-
MacroKinds::BANG => clean::MacroItem(clean::Macro {
762-
source: utils::display_macro_source(cx, name, &def),
763-
macro_rules: def.macro_rules,
764-
}),
758+
MacroKinds::BANG => clean::MacroItem(
759+
clean::Macro {
760+
source: utils::display_macro_source(cx, name, &def),
761+
macro_rules: def.macro_rules,
762+
},
763+
None,
764+
),
765765
MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro {
766766
kind: MacroKind::Derive,
767767
helpers: Vec::new(),
@@ -770,7 +770,14 @@ fn build_macro(
770770
kind: MacroKind::Attr,
771771
helpers: Vec::new(),
772772
}),
773-
_ => todo!("Handle macros with multiple kinds"),
773+
_ if macro_kinds == (MacroKinds::BANG | MacroKinds::ATTR) => clean::MacroItem(
774+
clean::Macro {
775+
source: utils::display_macro_source(cx, name, &def),
776+
macro_rules: def.macro_rules,
777+
},
778+
Some(macro_kinds),
779+
),
780+
_ => panic!("unsupported macro kind {macro_kinds:?}"),
774781
},
775782
LoadedMacro::ProcMacro(ext) => {
776783
// Proc macros can only have a single kind

src/librustdoc/clean/mod.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2843,19 +2843,24 @@ fn clean_maybe_renamed_item<'tcx>(
28432843
generics: clean_generics(generics, cx),
28442844
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
28452845
}),
2846-
// FIXME: handle attributes and derives that aren't proc macros, and macros with
2847-
// multiple kinds
2848-
ItemKind::Macro(_, macro_def, MacroKinds::BANG) => MacroItem(Macro {
2849-
source: display_macro_source(cx, name, macro_def),
2850-
macro_rules: macro_def.macro_rules,
2851-
}),
2852-
ItemKind::Macro(_, _, MacroKinds::ATTR) => {
2853-
clean_proc_macro(item, &mut name, MacroKind::Attr, cx)
2854-
}
2855-
ItemKind::Macro(_, _, MacroKinds::DERIVE) => {
2856-
clean_proc_macro(item, &mut name, MacroKind::Derive, cx)
2857-
}
2858-
ItemKind::Macro(_, _, _) => todo!("Handle macros with multiple kinds"),
2846+
ItemKind::Macro(_, macro_def, kinds) => match kinds {
2847+
MacroKinds::BANG => MacroItem(
2848+
Macro {
2849+
source: display_macro_source(cx, name, macro_def),
2850+
macro_rules: macro_def.macro_rules,
2851+
},
2852+
None,
2853+
),
2854+
MacroKinds::ATTR => clean_proc_macro(item, &mut name, MacroKind::Attr, cx),
2855+
MacroKinds::DERIVE => clean_proc_macro(item, &mut name, MacroKind::Derive, cx),
2856+
_ => MacroItem(
2857+
Macro {
2858+
source: display_macro_source(cx, name, macro_def),
2859+
macro_rules: macro_def.macro_rules,
2860+
},
2861+
Some(kinds),
2862+
),
2863+
},
28592864
// proc macros can have a name set by attributes
28602865
ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
28612866
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)

src/librustdoc/clean/types.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use itertools::Either;
88
use rustc_abi::{ExternAbi, VariantIdx};
99
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
1010
use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation};
11-
use rustc_hir::def::{CtorKind, DefKind, Res};
11+
use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res};
1212
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
1313
use rustc_hir::lang_items::LangItem;
1414
use rustc_hir::{BodyId, ConstStability, Mutability, Stability, StableSince, find_attr};
@@ -664,6 +664,24 @@ impl Item {
664664
find_attr!(&self.attrs.other_attrs, AttributeKind::NonExhaustive(..))
665665
}
666666

667+
pub(crate) fn bang_macro_types(&self) -> Option<Vec<ItemType>> {
668+
match self.kind {
669+
ItemKind::MacroItem(_, None) => Some(vec![ItemType::Macro]),
670+
ItemKind::MacroItem(_, Some(kinds)) => Some(
671+
kinds
672+
.iter()
673+
.map(|kind| match kind {
674+
MacroKinds::BANG => ItemType::Macro,
675+
MacroKinds::ATTR => ItemType::ProcAttribute,
676+
MacroKinds::DERIVE => ItemType::ProcDerive,
677+
_ => panic!("unexpected macro kind {kind:?}"),
678+
})
679+
.collect::<Vec<_>>(),
680+
),
681+
_ => None,
682+
}
683+
}
684+
667685
/// Returns a documentation-level item type from the item.
668686
pub(crate) fn type_(&self) -> ItemType {
669687
ItemType::from(self)
@@ -953,7 +971,7 @@ pub(crate) enum ItemKind {
953971
ForeignStaticItem(Static, hir::Safety),
954972
/// `type`s from an extern block
955973
ForeignTypeItem,
956-
MacroItem(Macro),
974+
MacroItem(Macro, Option<MacroKinds>),
957975
ProcMacroItem(ProcMacro),
958976
PrimitiveItem(PrimitiveType),
959977
/// A required associated constant in a trait declaration.
@@ -1008,7 +1026,7 @@ impl ItemKind {
10081026
| ForeignFunctionItem(_, _)
10091027
| ForeignStaticItem(_, _)
10101028
| ForeignTypeItem
1011-
| MacroItem(_)
1029+
| MacroItem(..)
10121030
| ProcMacroItem(_)
10131031
| PrimitiveItem(_)
10141032
| RequiredAssocConstItem(..)
@@ -1040,7 +1058,7 @@ impl ItemKind {
10401058
| ForeignFunctionItem(_, _)
10411059
| ForeignStaticItem(_, _)
10421060
| ForeignTypeItem
1043-
| MacroItem(_)
1061+
| MacroItem(..)
10441062
| ProcMacroItem(_)
10451063
| PrimitiveItem(_)
10461064
)

src/librustdoc/fold.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub(crate) trait DocFolder: Sized {
8888
| ForeignFunctionItem(..)
8989
| ForeignStaticItem(..)
9090
| ForeignTypeItem
91-
| MacroItem(_)
91+
| MacroItem(..)
9292
| ProcMacroItem(_)
9393
| PrimitiveItem(_)
9494
| RequiredAssocConstItem(..)

src/librustdoc/html/render/context.rs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_middle::ty::TyCtxt;
1313
use rustc_session::Session;
1414
use rustc_span::edition::Edition;
1515
use rustc_span::{BytePos, FileName, Symbol, sym};
16+
use serde::ser::SerializeSeq;
1617
use tracing::info;
1718

1819
use super::print_item::{full_path, print_item, print_item_path};
@@ -165,6 +166,27 @@ impl SharedContext<'_> {
165166
}
166167
}
167168

169+
struct SidebarItem {
170+
name: String,
171+
is_actually_macro: bool,
172+
}
173+
174+
impl serde::Serialize for SidebarItem {
175+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
176+
where
177+
S: serde::Serializer,
178+
{
179+
if self.is_actually_macro {
180+
let mut seq = serializer.serialize_seq(Some(2))?;
181+
seq.serialize_element(&self.name)?;
182+
seq.serialize_element(&1)?;
183+
seq.end()
184+
} else {
185+
serializer.serialize_some(&Some(&self.name))
186+
}
187+
}
188+
}
189+
168190
impl<'tcx> Context<'tcx> {
169191
pub(crate) fn tcx(&self) -> TyCtxt<'tcx> {
170192
self.shared.tcx
@@ -305,7 +327,20 @@ impl<'tcx> Context<'tcx> {
305327
}
306328

307329
/// Construct a map of items shown in the sidebar to a plain-text summary of their docs.
308-
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<String>> {
330+
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<SidebarItem>> {
331+
fn build_sidebar_items_inner(
332+
name: Symbol,
333+
type_: ItemType,
334+
map: &mut BTreeMap<String, Vec<SidebarItem>>,
335+
inserted: &mut FxHashMap<ItemType, FxHashSet<Symbol>>,
336+
is_actually_macro: bool,
337+
) {
338+
if inserted.entry(type_).or_default().insert(name) {
339+
let type_ = type_.to_string();
340+
let name = name.to_string();
341+
map.entry(type_).or_default().push(SidebarItem { name, is_actually_macro });
342+
}
343+
}
309344
// BTreeMap instead of HashMap to get a sorted output
310345
let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new();
311346
let mut inserted: FxHashMap<ItemType, FxHashSet<Symbol>> = FxHashMap::default();
@@ -314,23 +349,24 @@ impl<'tcx> Context<'tcx> {
314349
if item.is_stripped() {
315350
continue;
316351
}
317-
318-
let short = item.type_();
319-
let myname = match item.name {
352+
let name = match item.name {
320353
None => continue,
321354
Some(s) => s,
322355
};
323-
if inserted.entry(short).or_default().insert(myname) {
324-
let short = short.to_string();
325-
let myname = myname.to_string();
326-
map.entry(short).or_default().push(myname);
356+
357+
if let Some(types) = item.bang_macro_types() {
358+
for type_ in types {
359+
build_sidebar_items_inner(name, type_, &mut map, &mut inserted, true);
360+
}
361+
} else {
362+
build_sidebar_items_inner(name, item.type_(), &mut map, &mut inserted, false);
327363
}
328364
}
329365

330366
match self.shared.module_sorting {
331367
ModuleSorting::Alphabetical => {
332368
for items in map.values_mut() {
333-
items.sort();
369+
items.sort_by(|a, b| a.name.cmp(&b.name));
334370
}
335371
}
336372
ModuleSorting::DeclarationOrder => {}
@@ -863,7 +899,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
863899
self.shared.fs.write(joint_dst, buf)?;
864900

865901
if !self.info.render_redirect_pages {
866-
self.shared.all.borrow_mut().append(full_path(self, item), &item_type);
902+
self.shared.all.borrow_mut().append(
903+
full_path(self, item),
904+
&item_type,
905+
item.bang_macro_types(),
906+
);
867907
}
868908
// If the item is a macro, redirect from the old macro URL (with !)
869909
// to the new one (without).

src/librustdoc/html/render/mod.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -503,33 +503,46 @@ impl AllTypes {
503503
}
504504
}
505505

506-
fn append(&mut self, item_name: String, item_type: &ItemType) {
506+
fn append(
507+
&mut self,
508+
item_name: String,
509+
item_type: &ItemType,
510+
extra_types: Option<Vec<ItemType>>,
511+
) {
507512
let mut url: Vec<_> = item_name.split("::").skip(1).collect();
508513
if let Some(name) = url.pop() {
509514
let new_url = format!("{}/{item_type}.{name}.html", url.join("/"));
510515
url.push(name);
511516
let name = url.join("::");
512-
match *item_type {
513-
ItemType::Struct => self.structs.insert(ItemEntry::new(new_url, name)),
514-
ItemType::Enum => self.enums.insert(ItemEntry::new(new_url, name)),
515-
ItemType::Union => self.unions.insert(ItemEntry::new(new_url, name)),
516-
ItemType::Primitive => self.primitives.insert(ItemEntry::new(new_url, name)),
517-
ItemType::Trait => self.traits.insert(ItemEntry::new(new_url, name)),
518-
ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)),
519-
ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)),
520-
ItemType::TypeAlias => self.type_aliases.insert(ItemEntry::new(new_url, name)),
521-
ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
522-
ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
523-
ItemType::ProcAttribute => {
524-
self.attribute_macros.insert(ItemEntry::new(new_url, name))
517+
if let Some(extra_types) = extra_types {
518+
for extra_type in extra_types {
519+
self.append_with_url(name.clone(), &extra_type, new_url.clone());
525520
}
526-
ItemType::ProcDerive => self.derive_macros.insert(ItemEntry::new(new_url, name)),
527-
ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(new_url, name)),
528-
_ => true,
529-
};
521+
} else {
522+
self.append_with_url(name, item_type, new_url);
523+
}
530524
}
531525
}
532526

527+
fn append_with_url(&mut self, name: String, item_type: &ItemType, url: String) {
528+
match *item_type {
529+
ItemType::Struct => self.structs.insert(ItemEntry::new(url, name)),
530+
ItemType::Enum => self.enums.insert(ItemEntry::new(url, name)),
531+
ItemType::Union => self.unions.insert(ItemEntry::new(url, name)),
532+
ItemType::Primitive => self.primitives.insert(ItemEntry::new(url, name)),
533+
ItemType::Trait => self.traits.insert(ItemEntry::new(url, name)),
534+
ItemType::Macro => self.macros.insert(ItemEntry::new(url, name)),
535+
ItemType::Function => self.functions.insert(ItemEntry::new(url, name)),
536+
ItemType::TypeAlias => self.type_aliases.insert(ItemEntry::new(url, name)),
537+
ItemType::Static => self.statics.insert(ItemEntry::new(url, name)),
538+
ItemType::Constant => self.constants.insert(ItemEntry::new(url, name)),
539+
ItemType::ProcAttribute => self.attribute_macros.insert(ItemEntry::new(url, name)),
540+
ItemType::ProcDerive => self.derive_macros.insert(ItemEntry::new(url, name)),
541+
ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(url, name)),
542+
_ => true,
543+
};
544+
}
545+
533546
fn item_sections(&self) -> FxHashSet<ItemSection> {
534547
let mut sections = FxHashSet::default();
535548

0 commit comments

Comments
 (0)