Skip to content

Commit da1997e

Browse files
Support new bang macro kinds in rustdoc
1 parent ebe145e commit da1997e

File tree

11 files changed

+330
-204
lines changed

11 files changed

+330
-204
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
@@ -764,13 +763,14 @@ fn build_macro(
764763
macro_kinds: MacroKinds,
765764
) -> clean::ItemKind {
766765
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
767-
// FIXME: handle attributes and derives that aren't proc macros, and macros with multiple
768-
// kinds
769766
LoadedMacro::MacroDef { def, .. } => match macro_kinds {
770-
MacroKinds::BANG => clean::MacroItem(clean::Macro {
771-
source: utils::display_macro_source(cx, name, &def),
772-
macro_rules: def.macro_rules,
773-
}),
767+
MacroKinds::BANG => clean::MacroItem(
768+
clean::Macro {
769+
source: utils::display_macro_source(cx, name, &def),
770+
macro_rules: def.macro_rules,
771+
},
772+
None,
773+
),
774774
MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro {
775775
kind: MacroKind::Derive,
776776
helpers: Vec::new(),
@@ -779,7 +779,14 @@ fn build_macro(
779779
kind: MacroKind::Attr,
780780
helpers: Vec::new(),
781781
}),
782-
_ => todo!("Handle macros with multiple kinds"),
782+
_ if macro_kinds == (MacroKinds::BANG | MacroKinds::ATTR) => clean::MacroItem(
783+
clean::Macro {
784+
source: utils::display_macro_source(cx, name, &def),
785+
macro_rules: def.macro_rules,
786+
},
787+
Some(macro_kinds),
788+
),
789+
_ => panic!("unsupported macro kind {macro_kinds:?}"),
783790
},
784791
LoadedMacro::ProcMacro(ext) => {
785792
// 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
@@ -2841,19 +2841,24 @@ fn clean_maybe_renamed_item<'tcx>(
28412841
generics: clean_generics(generics, cx),
28422842
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
28432843
}),
2844-
// FIXME: handle attributes and derives that aren't proc macros, and macros with
2845-
// multiple kinds
2846-
ItemKind::Macro(_, macro_def, MacroKinds::BANG) => MacroItem(Macro {
2847-
source: display_macro_source(cx, name, macro_def),
2848-
macro_rules: macro_def.macro_rules,
2849-
}),
2850-
ItemKind::Macro(_, _, MacroKinds::ATTR) => {
2851-
clean_proc_macro(item, &mut name, MacroKind::Attr, cx)
2852-
}
2853-
ItemKind::Macro(_, _, MacroKinds::DERIVE) => {
2854-
clean_proc_macro(item, &mut name, MacroKind::Derive, cx)
2855-
}
2856-
ItemKind::Macro(_, _, _) => todo!("Handle macros with multiple kinds"),
2844+
ItemKind::Macro(_, macro_def, kinds) => match kinds {
2845+
MacroKinds::BANG => MacroItem(
2846+
Macro {
2847+
source: display_macro_source(cx, name, macro_def),
2848+
macro_rules: macro_def.macro_rules,
2849+
},
2850+
None,
2851+
),
2852+
MacroKinds::ATTR => clean_proc_macro(item, &mut name, MacroKind::Attr, cx),
2853+
MacroKinds::DERIVE => clean_proc_macro(item, &mut name, MacroKind::Derive, cx),
2854+
_ => MacroItem(
2855+
Macro {
2856+
source: display_macro_source(cx, name, macro_def),
2857+
macro_rules: macro_def.macro_rules,
2858+
},
2859+
Some(kinds),
2860+
),
2861+
},
28572862
// proc macros can have a name set by attributes
28582863
ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
28592864
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)

src/librustdoc/clean/types.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_abi::{ExternAbi, VariantIdx};
99
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
1010
use rustc_data_structures::thin_vec::ThinVec;
1111
use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation};
12-
use rustc_hir::def::{CtorKind, DefKind, Res};
12+
use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res};
1313
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
1414
use rustc_hir::lang_items::LangItem;
1515
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)
@@ -834,7 +852,7 @@ pub(crate) enum ItemKind {
834852
ForeignStaticItem(Static, hir::Safety),
835853
/// `type`s from an extern block
836854
ForeignTypeItem,
837-
MacroItem(Macro),
855+
MacroItem(Macro, Option<MacroKinds>),
838856
ProcMacroItem(ProcMacro),
839857
PrimitiveItem(PrimitiveType),
840858
/// A required associated constant in a trait declaration.
@@ -889,7 +907,7 @@ impl ItemKind {
889907
| ForeignFunctionItem(_, _)
890908
| ForeignStaticItem(_, _)
891909
| ForeignTypeItem
892-
| MacroItem(_)
910+
| MacroItem(..)
893911
| ProcMacroItem(_)
894912
| PrimitiveItem(_)
895913
| RequiredAssocConstItem(..)

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};
@@ -166,6 +167,27 @@ impl SharedContext<'_> {
166167
}
167168
}
168169

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

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

331367
match self.shared.module_sorting {
332368
ModuleSorting::Alphabetical => {
333369
for items in map.values_mut() {
334-
items.sort();
370+
items.sort_by(|a, b| a.name.cmp(&b.name));
335371
}
336372
}
337373
ModuleSorting::DeclarationOrder => {}
@@ -864,7 +900,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
864900
self.shared.fs.write(joint_dst, buf)?;
865901

866902
if !self.info.render_redirect_pages {
867-
self.shared.all.borrow_mut().append(full_path(self, item), &item_type);
903+
self.shared.all.borrow_mut().append(
904+
full_path(self, item),
905+
&item_type,
906+
item.bang_macro_types(),
907+
);
868908
}
869909
// If the item is a macro, redirect from the old macro URL (with !)
870910
// 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
@@ -505,33 +505,46 @@ impl AllTypes {
505505
}
506506
}
507507

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

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

0 commit comments

Comments
 (0)