Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustdoc: give proc-macros their own pages #54577

Merged
merged 8 commits into from
Sep 29, 2018
68 changes: 39 additions & 29 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use std::iter::once;

use syntax::ast;
use syntax::ext::base::MacroKind;
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax_pos::Span;

use rustc::hir;
Expand Down Expand Up @@ -105,12 +105,12 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
record_extern_fqn(cx, did, clean::TypeKind::Const);
clean::ConstantItem(build_const(cx, did))
}
// FIXME(misdreavus): if attributes/derives come down here we should probably document them
// separately
// FIXME: proc-macros don't propagate attributes or spans across crates, so they look empty
Def::Macro(did, MacroKind::Bang) => {
record_extern_fqn(cx, did, clean::TypeKind::Macro);
if let Some(mac) = build_macro(cx, did, name) {
clean::MacroItem(mac)
let mac = build_macro(cx, did, name);
if let clean::MacroItem(..) = mac {
record_extern_fqn(cx, did, clean::TypeKind::Macro);
mac
} else {
return None;
}
Expand Down Expand Up @@ -442,31 +442,41 @@ fn build_static(cx: &DocContext, did: DefId, mutable: bool) -> clean::Static {
}
}

fn build_macro(cx: &DocContext, did: DefId, name: ast::Name) -> Option<clean::Macro> {
fn build_macro(cx: &DocContext, did: DefId, name: ast::Name) -> clean::ItemEnum {
let imported_from = cx.tcx.original_crate_name(did.krate);
let def = match cx.cstore.load_macro_untracked(did, cx.sess()) {
LoadedMacro::MacroDef(macro_def) => macro_def,
// FIXME(jseyfried): document proc macro re-exports
LoadedMacro::ProcMacro(..) => return None,
};

let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.node {
let tts: Vec<_> = def.stream().into_trees().collect();
tts.chunks(4).map(|arm| arm[0].span()).collect()
} else {
unreachable!()
};

let source = format!("macro_rules! {} {{\n{}}}",
name.clean(cx),
matchers.iter().map(|span| {
format!(" {} => {{ ... }};\n", span.to_src(cx))
}).collect::<String>());
match cx.cstore.load_macro_untracked(did, cx.sess()) {
LoadedMacro::MacroDef(def) => {
let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.node {
let tts: Vec<_> = def.stream().into_trees().collect();
tts.chunks(4).map(|arm| arm[0].span()).collect()
} else {
unreachable!()
};

let source = format!("macro_rules! {} {{\n{}}}",
name.clean(cx),
matchers.iter().map(|span| {
format!(" {} => {{ ... }};\n", span.to_src(cx))
}).collect::<String>());

clean::MacroItem(clean::Macro {
source,
imported_from: Some(imported_from).clean(cx),
})
}
LoadedMacro::ProcMacro(ext) => {
let helpers = match &*ext {
&SyntaxExtension::ProcMacroDerive(_, ref syms, ..) => { syms.clean(cx) }
_ => Vec::new(),
};

clean::ProcMacroItem(clean::ProcMacro {
kind: ext.kind(),
helpers,
})
}
}

Some(clean::Macro {
source,
imported_from: Some(imported_from).clean(cx),
})
}

/// A trait's generics clause actually contains all of the predicates for all of
Expand Down
36 changes: 35 additions & 1 deletion src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use self::Visibility::{Public, Inherited};
use rustc_target::spec::abi::Abi;
use syntax::ast::{self, AttrStyle, Ident};
use syntax::attr;
use syntax::ext::base::MacroKind;
use syntax::source_map::{dummy_spanned, Spanned};
use syntax::ptr::P;
use syntax::symbol::keywords::{self, Keyword};
Expand Down Expand Up @@ -527,6 +528,7 @@ pub enum ItemEnum {
/// `type`s from an extern block
ForeignTypeItem,
MacroItem(Macro),
ProcMacroItem(ProcMacro),
PrimitiveItem(PrimitiveType),
AssociatedConstItem(Type, Option<String>),
AssociatedTypeItem(Vec<GenericBound>, Option<Type>),
Expand Down Expand Up @@ -588,6 +590,7 @@ impl Clean<Item> for doctree::Module {
items.extend(self.traits.iter().map(|x| x.clean(cx)));
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
items.extend(self.macros.iter().map(|x| x.clean(cx)));
items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));

// determine if we should display the inner contents or
// the outer `mod` item for the source code.
Expand Down Expand Up @@ -2189,6 +2192,8 @@ pub enum TypeKind {
Typedef,
Foreign,
Macro,
Attr,
Derive,
}

pub trait GetDefId {
Expand Down Expand Up @@ -3725,7 +3730,12 @@ pub fn register_def(cx: &DocContext, def: Def) -> DefId {
Def::Static(i, _) => (i, TypeKind::Static),
Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"),
TypeKind::Enum),
Def::Macro(i, _) => (i, TypeKind::Macro),
Def::Macro(i, mac_kind) => match mac_kind {
MacroKind::Bang => (i, TypeKind::Macro),
MacroKind::Attr => (i, TypeKind::Attr),
MacroKind::Derive => (i, TypeKind::Derive),
MacroKind::ProcMacroStub => unreachable!(),
},
Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
Def::SelfTy(_, Some(impl_def_id)) => {
return impl_def_id
Expand Down Expand Up @@ -3780,6 +3790,30 @@ impl Clean<Item> for doctree::Macro {
}
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ProcMacro {
pub kind: MacroKind,
pub helpers: Vec<String>,
}

impl Clean<Item> for doctree::ProcMacro {
fn clean(&self, cx: &DocContext) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
visibility: Some(Public),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
def_id: cx.tcx.hir.local_def_id(self.id),
inner: ProcMacroItem(ProcMacro {
kind: self.kind,
helpers: self.helpers.clean(cx),
}),
}
}
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Stability {
pub level: stability::StabilityLevel,
Expand Down
14 changes: 14 additions & 0 deletions src/librustdoc/doctree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub use self::StructType::*;
use syntax::ast;
use syntax::ast::{Name, NodeId};
use syntax::attr;
use syntax::ext::base::MacroKind;
use syntax::ptr::P;
use syntax::source_map::Spanned;
use syntax_pos::{self, Span};
Expand Down Expand Up @@ -46,6 +47,7 @@ pub struct Module {
pub impls: Vec<Impl>,
pub foreigns: Vec<hir::ForeignMod>,
pub macros: Vec<Macro>,
pub proc_macros: Vec<ProcMacro>,
pub is_crate: bool,
}

Expand Down Expand Up @@ -75,6 +77,7 @@ impl Module {
impls : Vec::new(),
foreigns : Vec::new(),
macros : Vec::new(),
proc_macros: Vec::new(),
is_crate : false,
}
}
Expand Down Expand Up @@ -264,6 +267,17 @@ pub struct Import {
pub whence: Span,
}

pub struct ProcMacro {
pub name: Name,
pub id: NodeId,
pub kind: MacroKind,
pub helpers: Vec<Name>,
pub attrs: hir::HirVec<ast::Attribute>,
pub whence: Span,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
}

pub fn struct_type_from_def(vdata: &hir::VariantData) -> StructType {
match *vdata {
hir::VariantData::Struct(..) => Plain,
Expand Down
24 changes: 22 additions & 2 deletions src/librustdoc/html/item_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//! Item types.

use std::fmt;
use syntax::ext::base::MacroKind;
use clean;

/// Item type. Corresponds to `clean::ItemEnum` variants.
Expand All @@ -19,6 +20,11 @@ use clean;
/// discriminants. JavaScript then is used to decode them into the original value.
/// Consequently, every change to this type should be synchronized to
/// the `itemTypes` mapping table in `static/main.js`.
///
/// In addition, code in `html::render` uses this enum to generate CSS classes, page prefixes, and
/// module headings. If you are adding to this enum and want to ensure that the sidebar also prints
/// a heading, edit the listing in `html/render.rs`, function `sidebar_module`. This uses an
/// ordering based on a helper function inside `item_module`, in the same file.
#[derive(Copy, PartialEq, Clone, Debug)]
pub enum ItemType {
Module = 0,
Expand All @@ -44,6 +50,8 @@ pub enum ItemType {
ForeignType = 20,
Keyword = 21,
Existential = 22,
ProcAttribute = 23,
ProcDerive = 24,
}


Expand Down Expand Up @@ -88,6 +96,12 @@ impl<'a> From<&'a clean::Item> for ItemType {
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
clean::ForeignTypeItem => ItemType::ForeignType,
clean::KeywordItem(..) => ItemType::Keyword,
clean::ProcMacroItem(ref mac) => match mac.kind {
MacroKind::Bang => ItemType::Macro,
MacroKind::Attr => ItemType::ProcAttribute,
MacroKind::Derive => ItemType::ProcDerive,
MacroKind::ProcMacroStub => unreachable!(),
}
clean::StrippedItem(..) => unreachable!(),
}
}
Expand All @@ -107,7 +121,9 @@ impl From<clean::TypeKind> for ItemType {
clean::TypeKind::Variant => ItemType::Variant,
clean::TypeKind::Typedef => ItemType::Typedef,
clean::TypeKind::Foreign => ItemType::ForeignType,
clean::TypeKind::Macro => ItemType::Macro,
clean::TypeKind::Macro => ItemType::Macro,
clean::TypeKind::Attr => ItemType::ProcAttribute,
clean::TypeKind::Derive => ItemType::ProcDerive,
}
}
}
Expand Down Expand Up @@ -138,6 +154,8 @@ impl ItemType {
ItemType::ForeignType => "foreigntype",
ItemType::Keyword => "keyword",
ItemType::Existential => "existential",
ItemType::ProcAttribute => "attr",
ItemType::ProcDerive => "derive",
}
}

Expand Down Expand Up @@ -166,7 +184,9 @@ impl ItemType {
ItemType::Constant |
ItemType::AssociatedConst => NameSpace::Value,

ItemType::Macro => NameSpace::Macro,
ItemType::Macro |
ItemType::ProcAttribute |
ItemType::ProcDerive => NameSpace::Macro,

ItemType::Keyword => NameSpace::Keyword,
}
Expand Down
Loading