use crate::clean::auto_trait::AutoTraitFinder;
use crate::clean::blanket_impl::BlanketImplFinder;
use crate::clean::{
- inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
- Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
+ inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
+ ItemKind, Lifetime, Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type,
+ TypeBinding, Visibility,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
+use rustc_ast as ast;
+use rustc_ast::tokenstream::TokenTree;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
+use std::fmt::Write as _;
use std::mem;
#[cfg(test)]
cx.cache.owned_box_did = cx.tcx.lang_items().owned_box();
let mut externs = Vec::new();
- for &cnum in cx.tcx.crates().iter() {
- externs.push((cnum, cnum.clean(cx)));
+ for &cnum in cx.tcx.crates(()).iter() {
+ externs.push(ExternalCrate { crate_num: cnum });
// Analyze doc-reachability for extern items
LibEmbargoVisitor::new(cx).visit_lib(cnum);
}
- externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
+ externs.sort_unstable_by_key(|e| e.crate_num);
// Clean the crate, translating the entire librustc_ast AST to one that is
// understood by rustdoc.
_ => unreachable!(),
}
- let local_crate = LOCAL_CRATE.clean(cx);
+ let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
let src = local_crate.src(cx.tcx);
let name = local_crate.name(cx.tcx);
let primitives = local_crate.primitives(cx.tcx);
crate fn strip_type(ty: Type) -> Type {
match ty {
- Type::ResolvedPath { path, param_names, did, is_generic } => {
- Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
+ Type::ResolvedPath { path, did, is_generic } => {
+ Type::ResolvedPath { path: strip_path(&path), did, is_generic }
+ }
+ Type::DynTrait(mut bounds, lt) => {
+ let first = bounds.remove(0);
+ let stripped_trait = strip_type(first.trait_);
+
+ bounds.insert(
+ 0,
+ PolyTrait { trait_: stripped_trait, generic_params: first.generic_params },
+ );
+ Type::DynTrait(bounds, lt)
}
Type::Tuple(inner_tys) => {
Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
}
}
-crate trait ToSource {
- fn to_src(&self, cx: &DocContext<'_>) -> String;
-}
-
-impl ToSource for rustc_span::Span {
- fn to_src(&self, cx: &DocContext<'_>) -> String {
- debug!("converting span {:?} to snippet", self);
- let sn = match cx.sess().source_map().span_to_snippet(*self) {
- Ok(x) => x,
- Err(_) => String::new(),
- };
- debug!("got snippet {}", sn);
- sn
- }
-}
-
crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
use rustc_hir::*;
debug!("trying to get a name from pattern: {:?}", p);
PatKind::Wild | PatKind::Struct(..) => return kw::Underscore,
PatKind::Binding(_, _, ident, _) => return ident.name,
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
- PatKind::Or(ref pats) => pats
- .iter()
- .map(|p| name_from_pat(&**p).to_string())
- .collect::<Vec<String>>()
- .join(" | "),
+ PatKind::Or(ref pats) => {
+ pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ")
+ }
PatKind::Tuple(ref elts, _) => format!(
"({})",
- elts.iter()
- .map(|p| name_from_pat(&**p).to_string())
- .collect::<Vec<String>>()
- .join(", ")
+ elts.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(", ")
),
PatKind::Box(ref p) => return name_from_pat(&**p),
PatKind::Ref(ref p, _) => return name_from_pat(&**p),
}
PatKind::Range(..) => return kw::Underscore,
PatKind::Slice(ref begin, ref mid, ref end) => {
- let begin = begin.iter().map(|p| name_from_pat(&**p).to_string());
+ let begin = begin.iter().map(|p| name_from_pat(p).to_string());
let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
- let end = end.iter().map(|p| name_from_pat(&**p).to_string());
+ let end = end.iter().map(|p| name_from_pat(p).to_string());
format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
}
})
_ => false,
};
let did = register_res(cx, path.res);
- ResolvedPath { path, param_names: None, did, is_generic }
+ ResolvedPath { path, did, is_generic }
}
crate fn get_auto_trait_and_blanket_impls(
///
/// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
crate const DOC_RUST_LANG_ORG_CHANNEL: &'static str = env!("DOC_RUST_LANG_ORG_CHANNEL");
+
+/// Render a sequence of macro arms in a format suitable for displaying to the user
+/// as part of an item declaration.
+pub(super) fn render_macro_arms<'a>(
+ matchers: impl Iterator<Item = &'a TokenTree>,
+ arm_delim: &str,
+) -> String {
+ let mut out = String::new();
+ for matcher in matchers {
+ writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(matcher), arm_delim).unwrap();
+ }
+ out
+}
+
+/// Render a macro matcher in a format suitable for displaying to the user
+/// as part of an item declaration.
+pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String {
+ rustc_ast_pretty::pprust::tt_to_string(matcher)
+}
+
+pub(super) fn display_macro_source(
+ cx: &mut DocContext<'_>,
+ name: Symbol,
+ def: &ast::MacroDef,
+ def_id: DefId,
+ vis: impl Clean<Visibility>,
+) -> String {
+ let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
+ // Extract the spans of all matchers. They represent the "interface" of the macro.
+ let matchers = tts.chunks(4).map(|arm| &arm[0]);
+
+ if def.macro_rules {
+ format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
+ } else {
+ let vis = vis.clean(cx);
+
+ if matchers.len() <= 1 {
+ format!(
+ "{}macro {}{} {{\n ...\n}}",
+ vis.to_src_with_space(cx.tcx, def_id),
+ name,
+ matchers.map(render_macro_matcher).collect::<String>(),
+ )
+ } else {
+ format!(
+ "{}macro {} {{\n{}}}",
+ vis.to_src_with_space(cx.tcx, def_id),
+ name,
+ render_macro_arms(matchers, ","),
+ )
+ }
+ }
+}