Skip to content

Commit 3552177

Browse files
Support new bang macro kinds in rustdoc
1 parent 2c1ac85 commit 3552177

File tree

11 files changed

+322
-200
lines changed

11 files changed

+322
-200
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
@@ -2845,19 +2845,24 @@ fn clean_maybe_renamed_item<'tcx>(
28452845
generics: clean_generics(generics, cx),
28462846
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
28472847
}),
2848-
// FIXME: handle attributes and derives that aren't proc macros, and macros with
2849-
// multiple kinds
2850-
ItemKind::Macro(_, macro_def, MacroKinds::BANG) => MacroItem(Macro {
2851-
source: display_macro_source(cx, name, macro_def),
2852-
macro_rules: macro_def.macro_rules,
2853-
}),
2854-
ItemKind::Macro(_, _, MacroKinds::ATTR) => {
2855-
clean_proc_macro(item, &mut name, MacroKind::Attr, cx)
2856-
}
2857-
ItemKind::Macro(_, _, MacroKinds::DERIVE) => {
2858-
clean_proc_macro(item, &mut name, MacroKind::Derive, cx)
2859-
}
2860-
ItemKind::Macro(_, _, _) => todo!("Handle macros with multiple kinds"),
2848+
ItemKind::Macro(_, macro_def, kinds) => match kinds {
2849+
MacroKinds::BANG => MacroItem(
2850+
Macro {
2851+
source: display_macro_source(cx, name, macro_def),
2852+
macro_rules: macro_def.macro_rules,
2853+
},
2854+
None,
2855+
),
2856+
MacroKinds::ATTR => clean_proc_macro(item, &mut name, MacroKind::Attr, cx),
2857+
MacroKinds::DERIVE => clean_proc_macro(item, &mut name, MacroKind::Derive, cx),
2858+
_ => MacroItem(
2859+
Macro {
2860+
source: display_macro_source(cx, name, macro_def),
2861+
macro_rules: macro_def.macro_rules,
2862+
},
2863+
Some(kinds),
2864+
),
2865+
},
28612866
// proc macros can have a name set by attributes
28622867
ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
28632868
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};
@@ -637,6 +637,24 @@ impl Item {
637637
find_attr!(&self.attrs.other_attrs, AttributeKind::NonExhaustive(..))
638638
}
639639

640+
pub(crate) fn bang_macro_types(&self) -> Option<Vec<ItemType>> {
641+
match self.kind {
642+
ItemKind::MacroItem(_, None) => Some(vec![ItemType::Macro]),
643+
ItemKind::MacroItem(_, Some(kinds)) => Some(
644+
kinds
645+
.iter()
646+
.map(|kind| match kind {
647+
MacroKinds::BANG => ItemType::Macro,
648+
MacroKinds::ATTR => ItemType::ProcAttribute,
649+
MacroKinds::DERIVE => ItemType::ProcDerive,
650+
_ => panic!("unexpected macro kind {kind:?}"),
651+
})
652+
.collect::<Vec<_>>(),
653+
),
654+
_ => None,
655+
}
656+
}
657+
640658
/// Returns a documentation-level item type from the item.
641659
pub(crate) fn type_(&self) -> ItemType {
642660
ItemType::from(self)
@@ -924,7 +942,7 @@ pub(crate) enum ItemKind {
924942
ForeignStaticItem(Static, hir::Safety),
925943
/// `type`s from an extern block
926944
ForeignTypeItem,
927-
MacroItem(Macro),
945+
MacroItem(Macro, Option<MacroKinds>),
928946
ProcMacroItem(ProcMacro),
929947
PrimitiveItem(PrimitiveType),
930948
/// A required associated constant in a trait declaration.
@@ -974,7 +992,7 @@ impl ItemKind {
974992
| ForeignFunctionItem(_, _)
975993
| ForeignStaticItem(_, _)
976994
| ForeignTypeItem
977-
| MacroItem(_)
995+
| MacroItem(..)
978996
| ProcMacroItem(_)
979997
| PrimitiveItem(_)
980998
| RequiredAssocConstItem(..)
@@ -1005,7 +1023,7 @@ impl ItemKind {
10051023
| ForeignFunctionItem(_, _)
10061024
| ForeignStaticItem(_, _)
10071025
| ForeignTypeItem
1008-
| MacroItem(_)
1026+
| MacroItem(..)
10091027
| ProcMacroItem(_)
10101028
| PrimitiveItem(_)
10111029
)

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::{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};
@@ -163,6 +164,27 @@ impl SharedContext<'_> {
163164
}
164165
}
165166

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

292314
/// Construct a map of items shown in the sidebar to a plain-text summary of their docs.
293-
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<String>> {
315+
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<SidebarItem>> {
316+
fn build_sidebar_items_inner(
317+
name: Symbol,
318+
type_: ItemType,
319+
map: &mut BTreeMap<String, Vec<SidebarItem>>,
320+
inserted: &mut FxHashMap<ItemType, FxHashSet<Symbol>>,
321+
is_actually_macro: bool,
322+
) {
323+
if inserted.entry(type_).or_default().insert(name) {
324+
let type_ = type_.to_string();
325+
let name = name.to_string();
326+
map.entry(type_).or_default().push(SidebarItem { name, is_actually_macro });
327+
}
328+
}
294329
// BTreeMap instead of HashMap to get a sorted output
295330
let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new();
296331
let mut inserted: FxHashMap<ItemType, FxHashSet<Symbol>> = FxHashMap::default();
@@ -299,23 +334,24 @@ impl<'tcx> Context<'tcx> {
299334
if item.is_stripped() {
300335
continue;
301336
}
302-
303-
let short = item.type_();
304-
let myname = match item.name {
337+
let name = match item.name {
305338
None => continue,
306339
Some(s) => s,
307340
};
308-
if inserted.entry(short).or_default().insert(myname) {
309-
let short = short.to_string();
310-
let myname = myname.to_string();
311-
map.entry(short).or_default().push(myname);
341+
342+
if let Some(types) = item.bang_macro_types() {
343+
for type_ in types {
344+
build_sidebar_items_inner(name, type_, &mut map, &mut inserted, true);
345+
}
346+
} else {
347+
build_sidebar_items_inner(name, item.type_(), &mut map, &mut inserted, false);
312348
}
313349
}
314350

315351
match self.shared.module_sorting {
316352
ModuleSorting::Alphabetical => {
317353
for items in map.values_mut() {
318-
items.sort();
354+
items.sort_by(|a, b| a.name.cmp(&b.name));
319355
}
320356
}
321357
ModuleSorting::DeclarationOrder => {}
@@ -843,7 +879,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
843879
self.shared.fs.write(joint_dst, buf)?;
844880

845881
if !self.info.render_redirect_pages {
846-
self.shared.all.borrow_mut().append(full_path(self, item), &item_type);
882+
self.shared.all.borrow_mut().append(
883+
full_path(self, item),
884+
&item_type,
885+
item.bang_macro_types(),
886+
);
847887
}
848888
// If the item is a macro, redirect from the old macro URL (with !)
849889
// 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
@@ -381,33 +381,46 @@ impl AllTypes {
381381
}
382382
}
383383

384-
fn append(&mut self, item_name: String, item_type: &ItemType) {
384+
fn append(
385+
&mut self,
386+
item_name: String,
387+
item_type: &ItemType,
388+
extra_types: Option<Vec<ItemType>>,
389+
) {
385390
let mut url: Vec<_> = item_name.split("::").skip(1).collect();
386391
if let Some(name) = url.pop() {
387392
let new_url = format!("{}/{item_type}.{name}.html", url.join("/"));
388393
url.push(name);
389394
let name = url.join("::");
390-
match *item_type {
391-
ItemType::Struct => self.structs.insert(ItemEntry::new(new_url, name)),
392-
ItemType::Enum => self.enums.insert(ItemEntry::new(new_url, name)),
393-
ItemType::Union => self.unions.insert(ItemEntry::new(new_url, name)),
394-
ItemType::Primitive => self.primitives.insert(ItemEntry::new(new_url, name)),
395-
ItemType::Trait => self.traits.insert(ItemEntry::new(new_url, name)),
396-
ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)),
397-
ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)),
398-
ItemType::TypeAlias => self.type_aliases.insert(ItemEntry::new(new_url, name)),
399-
ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
400-
ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
401-
ItemType::ProcAttribute => {
402-
self.attribute_macros.insert(ItemEntry::new(new_url, name))
395+
if let Some(extra_types) = extra_types {
396+
for extra_type in extra_types {
397+
self.append_with_url(name.clone(), &extra_type, new_url.clone());
403398
}
404-
ItemType::ProcDerive => self.derive_macros.insert(ItemEntry::new(new_url, name)),
405-
ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(new_url, name)),
406-
_ => true,
407-
};
399+
} else {
400+
self.append_with_url(name, item_type, new_url);
401+
}
408402
}
409403
}
410404

405+
fn append_with_url(&mut self, name: String, item_type: &ItemType, url: String) {
406+
match *item_type {
407+
ItemType::Struct => self.structs.insert(ItemEntry::new(url, name)),
408+
ItemType::Enum => self.enums.insert(ItemEntry::new(url, name)),
409+
ItemType::Union => self.unions.insert(ItemEntry::new(url, name)),
410+
ItemType::Primitive => self.primitives.insert(ItemEntry::new(url, name)),
411+
ItemType::Trait => self.traits.insert(ItemEntry::new(url, name)),
412+
ItemType::Macro => self.macros.insert(ItemEntry::new(url, name)),
413+
ItemType::Function => self.functions.insert(ItemEntry::new(url, name)),
414+
ItemType::TypeAlias => self.type_aliases.insert(ItemEntry::new(url, name)),
415+
ItemType::Static => self.statics.insert(ItemEntry::new(url, name)),
416+
ItemType::Constant => self.constants.insert(ItemEntry::new(url, name)),
417+
ItemType::ProcAttribute => self.attribute_macros.insert(ItemEntry::new(url, name)),
418+
ItemType::ProcDerive => self.derive_macros.insert(ItemEntry::new(url, name)),
419+
ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(url, name)),
420+
_ => true,
421+
};
422+
}
423+
411424
fn item_sections(&self) -> FxHashSet<ItemSection> {
412425
let mut sections = FxHashSet::default();
413426

0 commit comments

Comments
 (0)