]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/visit_ast.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / src / librustdoc / visit_ast.rs
CommitLineData
0731742a
XL
1//! The Rust AST Visitor. Extracts useful information and massages it into a form
2//! usable for `clean`.
1a4d82fc 3
3dfed10e 4use rustc_ast as ast;
dfeec247
XL
5use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6use rustc_hir as hir;
7use rustc_hir::def::{DefKind, Res};
8use rustc_hir::def_id::{DefId, LOCAL_CRATE};
9use rustc_hir::Node;
ba9703b0
XL
10use rustc_middle::middle::privacy::AccessLevel;
11use rustc_middle::ty::TyCtxt;
dfeec247
XL
12use rustc_span::hygiene::MacroKind;
13use rustc_span::source_map::Spanned;
f9f354fc 14use rustc_span::symbol::{kw, sym, Ident, Symbol};
dfeec247 15use rustc_span::{self, Span};
1a4d82fc 16
0731742a 17use std::mem;
e9174d1e 18
416331ca 19use crate::clean::{self, AttributesExt, NestedAttributesExt};
dfeec247 20use crate::core;
9fa01778
XL
21use crate::doctree::*;
22
416331ca 23// FIXME: Should this be replaced with tcx.def_path_str?
dfeec247 24fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<String> {
416331ca
XL
25 let crate_name = tcx.crate_name(did.krate).to_string();
26 let relative = tcx.def_path(did).data.into_iter().filter_map(|elem| {
27 // extern blocks have an empty name
28 let s = elem.data.to_string();
dfeec247 29 if !s.is_empty() { Some(s) } else { None }
416331ca
XL
30 });
31 std::iter::once(crate_name).chain(relative).collect()
32}
1a4d82fc 33
0731742a
XL
34// Also, is there some reason that this doesn't use the 'visit'
35// framework from syntax?.
1a4d82fc 36
532ac7d7 37pub struct RustdocVisitor<'a, 'tcx> {
e1599b0c 38 cx: &'a mut core::DocContext<'tcx>,
48663c56 39 view_item_stack: FxHashSet<hir::HirId>,
476ff2be 40 inlining: bool,
0731742a 41 /// Are the current module and all of its parents public?
476ff2be 42 inside_public_path: bool,
416331ca 43 exact_paths: FxHashMap<DefId, Vec<String>>,
1a4d82fc
JJ
44}
45
532ac7d7 46impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
dfeec247 47 pub fn new(cx: &'a mut core::DocContext<'tcx>) -> RustdocVisitor<'a, 'tcx> {
2c00a5a8 48 // If the root is re-exported, terminate all recursion.
0bf4aa26 49 let mut stack = FxHashSet::default();
48663c56 50 stack.insert(hir::CRATE_HIR_ID);
1a4d82fc 51 RustdocVisitor {
3b2f2976 52 cx,
1a4d82fc 53 view_item_stack: stack,
476ff2be
SL
54 inlining: false,
55 inside_public_path: true,
416331ca 56 exact_paths: FxHashMap::default(),
1a4d82fc
JJ
57 }
58 }
59
0531ce1d 60 fn store_path(&mut self, did: DefId) {
416331ca
XL
61 let tcx = self.cx.tcx;
62 self.exact_paths.entry(did).or_insert_with(|| def_id_to_path(tcx, did));
9cc50fc6
SL
63 }
64
f035d41b 65 pub fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> {
dfeec247 66 let mut module = self.visit_mod_contents(
ba9703b0
XL
67 krate.item.span,
68 krate.item.attrs,
dfeec247
XL
69 &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
70 hir::CRATE_HIR_ID,
ba9703b0 71 &krate.item.module,
dfeec247 72 None,
dc9dc135 73 );
dfeec247
XL
74 // Attach the crate's exported macros to the top-level module:
75 module
76 .macros
77 .extend(krate.exported_macros.iter().map(|def| self.visit_local_macro(def, None)));
dc9dc135 78 module.is_crate = true;
0531ce1d 79
e1599b0c 80 self.cx.renderinfo.get_mut().exact_paths = self.exact_paths;
416331ca
XL
81
82 module
1a4d82fc
JJ
83 }
84
dfeec247
XL
85 fn visit_variant_data(
86 &mut self,
f035d41b 87 item: &'tcx hir::Item<'_>,
f9f354fc 88 name: Symbol,
f035d41b
XL
89 sd: &'tcx hir::VariantData<'_>,
90 generics: &'tcx hir::Generics<'_>,
dfeec247 91 ) -> Struct<'tcx> {
416331ca 92 debug!("visiting struct");
1a4d82fc
JJ
93 let struct_type = struct_type_from_def(&*sd);
94 Struct {
532ac7d7 95 id: item.hir_id,
3b2f2976
XL
96 struct_type,
97 name,
dc9dc135 98 vis: &item.vis,
dc9dc135
XL
99 attrs: &item.attrs,
100 generics,
101 fields: sd.fields(),
1b1a35ee 102 span: item.span,
1a4d82fc
JJ
103 }
104 }
105
dfeec247
XL
106 fn visit_union_data(
107 &mut self,
f035d41b 108 item: &'tcx hir::Item<'_>,
f9f354fc 109 name: Symbol,
f035d41b
XL
110 sd: &'tcx hir::VariantData<'_>,
111 generics: &'tcx hir::Generics<'_>,
dfeec247 112 ) -> Union<'tcx> {
416331ca 113 debug!("visiting union");
9e0c209e
SL
114 let struct_type = struct_type_from_def(&*sd);
115 Union {
532ac7d7 116 id: item.hir_id,
3b2f2976
XL
117 struct_type,
118 name,
dc9dc135 119 vis: &item.vis,
dc9dc135
XL
120 attrs: &item.attrs,
121 generics,
122 fields: sd.fields(),
1b1a35ee 123 span: item.span,
9e0c209e
SL
124 }
125 }
126
dfeec247
XL
127 fn visit_enum_def(
128 &mut self,
f035d41b 129 it: &'tcx hir::Item<'_>,
f9f354fc 130 name: Symbol,
f035d41b
XL
131 def: &'tcx hir::EnumDef<'_>,
132 generics: &'tcx hir::Generics<'_>,
dfeec247 133 ) -> Enum<'tcx> {
416331ca 134 debug!("visiting enum");
1a4d82fc 135 Enum {
3b2f2976 136 name,
dfeec247
XL
137 variants: def
138 .variants
139 .iter()
140 .map(|v| Variant {
141 name: v.ident.name,
142 id: v.id,
143 attrs: &v.attrs,
144 def: &v.data,
1b1a35ee 145 span: v.span,
dfeec247
XL
146 })
147 .collect(),
dc9dc135 148 vis: &it.vis,
dc9dc135
XL
149 generics,
150 attrs: &it.attrs,
532ac7d7 151 id: it.hir_id,
1b1a35ee 152 span: it.span,
1a4d82fc
JJ
153 }
154 }
155
dfeec247
XL
156 fn visit_fn(
157 &mut self,
158 om: &mut Module<'tcx>,
f035d41b 159 item: &'tcx hir::Item<'_>,
f9f354fc 160 name: Symbol,
f035d41b 161 decl: &'tcx hir::FnDecl<'_>,
dfeec247 162 header: hir::FnHeader,
f035d41b 163 generics: &'tcx hir::Generics<'_>,
dfeec247
XL
164 body: hir::BodyId,
165 ) {
416331ca 166 debug!("visiting fn");
f9f354fc 167 let macro_kind = item.attrs.iter().find_map(|a| {
3dfed10e 168 if a.has_name(sym::proc_macro) {
f9f354fc 169 Some(MacroKind::Bang)
3dfed10e 170 } else if a.has_name(sym::proc_macro_derive) {
f9f354fc 171 Some(MacroKind::Derive)
3dfed10e 172 } else if a.has_name(sym::proc_macro_attribute) {
f9f354fc
XL
173 Some(MacroKind::Attr)
174 } else {
175 None
176 }
177 });
0bf4aa26
XL
178 match macro_kind {
179 Some(kind) => {
180 let name = if kind == MacroKind::Derive {
dfeec247
XL
181 item.attrs
182 .lists(sym::proc_macro_derive)
f9f354fc 183 .find_map(|mi| mi.ident())
dfeec247
XL
184 .expect("proc-macro derives require a name")
185 .name
0bf4aa26
XL
186 } else {
187 name
188 };
189
190 let mut helpers = Vec::new();
48663c56 191 for mi in item.attrs.lists(sym::proc_macro_derive) {
3dfed10e 192 if !mi.has_name(sym::attributes) {
0bf4aa26
XL
193 continue;
194 }
195
196 if let Some(list) = mi.meta_item_list() {
197 for inner_mi in list {
9fa01778
XL
198 if let Some(ident) = inner_mi.ident() {
199 helpers.push(ident.name);
0bf4aa26
XL
200 }
201 }
202 }
203 }
204
205 om.proc_macros.push(ProcMacro {
206 name,
532ac7d7 207 id: item.hir_id,
0bf4aa26
XL
208 kind,
209 helpers,
dc9dc135 210 attrs: &item.attrs,
1b1a35ee 211 span: item.span,
0bf4aa26
XL
212 });
213 }
214 None => {
215 om.fns.push(Function {
532ac7d7 216 id: item.hir_id,
dc9dc135 217 vis: &item.vis,
dc9dc135
XL
218 attrs: &item.attrs,
219 decl,
0bf4aa26 220 name,
1b1a35ee 221 span: item.span,
dc9dc135 222 generics,
0bf4aa26
XL
223 header,
224 body,
225 });
226 }
1a4d82fc
JJ
227 }
228 }
229
dfeec247
XL
230 fn visit_mod_contents(
231 &mut self,
232 span: Span,
233 attrs: &'tcx [ast::Attribute],
f035d41b 234 vis: &'tcx hir::Visibility<'_>,
dfeec247
XL
235 id: hir::HirId,
236 m: &'tcx hir::Mod<'tcx>,
f9f354fc 237 name: Option<Symbol>,
dfeec247 238 ) -> Module<'tcx> {
dc9dc135 239 let mut om = Module::new(name, attrs, vis);
1a4d82fc
JJ
240 om.where_outer = span;
241 om.where_inner = m.inner;
416331ca 242 om.id = id;
476ff2be
SL
243 // Keep track of if there were any private modules in the path.
244 let orig_inside_public_path = self.inside_public_path;
8faf50e0 245 self.inside_public_path &= vis.node.is_pub();
dfeec247 246 for i in m.item_ids {
dc9dc135 247 let item = self.cx.tcx.hir().expect_item(i.id);
92a42be0 248 self.visit_item(item, None, &mut om);
1a4d82fc 249 }
476ff2be 250 self.inside_public_path = orig_inside_public_path;
476ff2be 251 om
1a4d82fc
JJ
252 }
253
54a0048b
SL
254 /// Tries to resolve the target of a `pub use` statement and inlines the
255 /// target if it is defined locally and would not be documented otherwise,
256 /// or when it is specifically requested with `please_inline`.
257 /// (the latter is the case when the import is marked `doc(inline)`)
258 ///
259 /// Cross-crate inlining occurs later on during crate cleaning
260 /// and follows different rules.
261 ///
9fa01778 262 /// Returns `true` if the target has been inlined.
dfeec247
XL
263 fn maybe_inline_local(
264 &mut self,
265 id: hir::HirId,
266 res: Res,
f9f354fc 267 renamed: Option<Ident>,
dfeec247
XL
268 glob: bool,
269 om: &mut Module<'tcx>,
270 please_inline: bool,
271 ) -> bool {
48663c56 272 fn inherits_doc_hidden(cx: &core::DocContext<'_>, mut node: hir::HirId) -> bool {
0731742a 273 while let Some(id) = cx.tcx.hir().get_enclosing_scope(node) {
54a0048b 274 node = id;
dfeec247 275 if cx.tcx.hir().attrs(node).lists(sym::doc).has_word(sym::hidden) {
54a0048b
SL
276 return true;
277 }
48663c56 278 if node == hir::CRATE_HIR_ID {
54a0048b
SL
279 break;
280 }
281 }
282 false
283 }
284
48663c56 285 debug!("maybe_inline_local res: {:?}", res);
cc61c64b 286
476ff2be 287 let tcx = self.cx.tcx;
48663c56 288 let res_did = if let Some(did) = res.opt_def_id() {
9fa01778
XL
289 did
290 } else {
476ff2be 291 return false;
9fa01778 292 };
54a0048b 293
dc9dc135 294 let use_attrs = tcx.hir().attrs(id);
0731742a 295 // Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
dfeec247
XL
296 let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline)
297 || use_attrs.lists(sym::doc).has_word(sym::hidden);
a7813a04
XL
298
299 // For cross-crate impl inlining we need to know whether items are
0731742a 300 // reachable in documentation -- a previously nonreachable item can be
a7813a04 301 // made reachable by cross-crate inlining which we're checking here.
0731742a 302 // (this is done here because we need to know this upfront).
48663c56
XL
303 if !res_did.is_local() && !is_no_inline {
304 let attrs = clean::inline::load_attrs(self.cx, res_did);
305 let self_is_hidden = attrs.lists(sym::doc).has_word(sym::hidden);
3dfed10e
XL
306 if !self_is_hidden {
307 if let Res::Def(kind, did) = res {
308 if kind == DefKind::Mod {
309 crate::visit_lib::LibEmbargoVisitor::new(self.cx).visit_mod(did)
310 } else {
311 // All items need to be handled here in case someone wishes to link
312 // to them with intra-doc links
313 self.cx
314 .renderinfo
315 .get_mut()
316 .access_levels
317 .map
318 .insert(did, AccessLevel::Public);
dfeec247
XL
319 }
320 }
a7813a04 321 }
dfeec247 322 return false;
a7813a04
XL
323 }
324
f9f354fc 325 let res_hir_id = match res_did.as_local() {
3dfed10e 326 Some(n) => tcx.hir().local_def_id_to_hir_id(n),
dfeec247 327 None => return false,
a7813a04 328 };
54a0048b 329
48663c56
XL
330 let is_private = !self.cx.renderinfo.borrow().access_levels.is_public(res_did);
331 let is_hidden = inherits_doc_hidden(self.cx, res_hir_id);
54a0048b 332
0731742a 333 // Only inline if requested or if the item would otherwise be stripped.
54a0048b 334 if (!please_inline && !is_private && !is_hidden) || is_no_inline {
dfeec247 335 return false;
1a4d82fc 336 }
54a0048b 337
dfeec247
XL
338 if !self.view_item_stack.insert(res_hir_id) {
339 return false;
340 }
1a4d82fc 341
dc9dc135 342 let ret = match tcx.hir().get(res_hir_id) {
e74abb32 343 Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
476ff2be 344 let prev = mem::replace(&mut self.inlining, true);
dfeec247 345 for i in m.item_ids {
dc9dc135 346 let i = self.cx.tcx.hir().expect_item(i.id);
041b39d2 347 self.visit_item(i, None, om);
1a4d82fc 348 }
476ff2be 349 self.inlining = prev;
041b39d2
XL
350 true
351 }
b7449926 352 Node::Item(it) if !glob => {
041b39d2
XL
353 let prev = mem::replace(&mut self.inlining, true);
354 self.visit_item(it, renamed, om);
355 self.inlining = prev;
1a4d82fc
JJ
356 true
357 }
b7449926 358 Node::ForeignItem(it) if !glob => {
dc9dc135
XL
359 let prev = mem::replace(&mut self.inlining, true);
360 self.visit_foreign_item(it, renamed, om);
361 self.inlining = prev;
ff7c6d11
XL
362 true
363 }
0731742a
XL
364 Node::MacroDef(def) if !glob => {
365 om.macros.push(self.visit_local_macro(def, renamed.map(|i| i.name)));
366 true
367 }
1a4d82fc
JJ
368 _ => false,
369 };
48663c56 370 self.view_item_stack.remove(&res_hir_id);
c30ab7b3 371 ret
1a4d82fc
JJ
372 }
373
f035d41b
XL
374 fn visit_item(
375 &mut self,
376 item: &'tcx hir::Item<'_>,
377 renamed: Option<Ident>,
378 om: &mut Module<'tcx>,
379 ) {
416331ca 380 debug!("visiting item {:?}", item);
0731742a 381 let ident = renamed.unwrap_or(item.ident);
0531ce1d 382
8faf50e0 383 if item.vis.node.is_pub() {
416331ca 384 let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
f9f354fc 385 self.store_path(def_id.to_def_id());
0531ce1d
XL
386 }
387
e74abb32 388 match item.kind {
8faf50e0 389 hir::ItemKind::ForeignMod(ref fm) => {
dfeec247 390 for item in fm.items {
dc9dc135
XL
391 self.visit_foreign_item(item, None, om);
392 }
476ff2be
SL
393 }
394 // If we're inlining, skip private items.
8faf50e0
XL
395 _ if self.inlining && !item.vis.node.is_pub() => {}
396 hir::ItemKind::GlobalAsm(..) => {}
397 hir::ItemKind::ExternCrate(orig_name) => {
416331ca 398 let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
85aaf69f 399 om.extern_crates.push(ExternCrate {
dfeec247 400 cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id).unwrap_or(LOCAL_CRATE),
0731742a 401 name: ident.name,
dfeec247 402 path: orig_name.map(|x| x.to_string()),
dc9dc135
XL
403 vis: &item.vis,
404 attrs: &item.attrs,
1b1a35ee 405 span: item.span,
85aaf69f
SL
406 })
407 }
8faf50e0
XL
408 hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
409 hir::ItemKind::Use(ref path, kind) => {
476ff2be
SL
410 let is_glob = kind == hir::UseKind::Glob;
411
0731742a
XL
412 // Struct and variant constructors and proc macro stubs always show up alongside
413 // their definitions, we've already processed them so just discard these.
416331ca
XL
414 if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = path.res {
415 return;
94b46f34
XL
416 }
417
476ff2be
SL
418 // If there was a private module in the current path then don't bother inlining
419 // anything as it will probably be stripped anyway.
8faf50e0 420 if item.vis.node.is_pub() && self.inside_public_path {
dfeec247 421 let please_inline = item.attrs.iter().any(|item| match item.meta_item_list() {
3dfed10e
XL
422 Some(ref list) if item.has_name(sym::doc) => {
423 list.iter().any(|i| i.has_name(sym::inline))
85aaf69f 424 }
dfeec247 425 _ => false,
85aaf69f 426 });
0731742a 427 let ident = if is_glob { None } else { Some(ident) };
dfeec247
XL
428 if self.maybe_inline_local(
429 item.hir_id,
430 path.res,
431 ident,
432 is_glob,
433 om,
434 please_inline,
435 ) {
476ff2be 436 return;
85aaf69f 437 }
476ff2be
SL
438 }
439
85aaf69f 440 om.imports.push(Import {
0731742a 441 name: ident.name,
532ac7d7 442 id: item.hir_id,
dc9dc135
XL
443 vis: &item.vis,
444 attrs: &item.attrs,
445 path,
476ff2be 446 glob: is_glob,
1b1a35ee 447 span: item.span,
85aaf69f
SL
448 });
449 }
8faf50e0 450 hir::ItemKind::Mod(ref m) => {
dfeec247
XL
451 om.mods.push(self.visit_mod_contents(
452 item.span,
453 &item.attrs,
454 &item.vis,
455 item.hir_id,
456 m,
457 Some(ident.name),
458 ));
459 }
460 hir::ItemKind::Enum(ref ed, ref gen) => {
461 om.enums.push(self.visit_enum_def(item, ident.name, ed, gen))
462 }
463 hir::ItemKind::Struct(ref sd, ref gen) => {
464 om.structs.push(self.visit_variant_data(item, ident.name, sd, gen))
465 }
466 hir::ItemKind::Union(ref sd, ref gen) => {
467 om.unions.push(self.visit_union_data(item, ident.name, sd, gen))
468 }
469 hir::ItemKind::Fn(ref sig, ref gen, body) => {
470 self.visit_fn(om, item, ident.name, &sig.decl, sig.header, gen, body)
471 }
472 hir::ItemKind::TyAlias(ty, ref gen) => {
1a4d82fc 473 let t = Typedef {
dc9dc135
XL
474 ty,
475 gen,
0731742a 476 name: ident.name,
532ac7d7 477 id: item.hir_id,
dc9dc135 478 attrs: &item.attrs,
1b1a35ee 479 span: item.span,
dc9dc135 480 vis: &item.vis,
1a4d82fc
JJ
481 };
482 om.typedefs.push(t);
dfeec247 483 }
416331ca
XL
484 hir::ItemKind::OpaqueTy(ref opaque_ty) => {
485 let t = OpaqueTy {
486 opaque_ty,
0731742a 487 name: ident.name,
532ac7d7 488 id: item.hir_id,
dc9dc135 489 attrs: &item.attrs,
1b1a35ee 490 span: item.span,
dc9dc135 491 vis: &item.vis,
8faf50e0 492 };
416331ca 493 om.opaque_tys.push(t);
dfeec247
XL
494 }
495 hir::ItemKind::Static(type_, mutability, expr) => {
1a4d82fc 496 let s = Static {
dc9dc135
XL
497 type_,
498 mutability,
499 expr,
532ac7d7 500 id: item.hir_id,
0731742a 501 name: ident.name,
dc9dc135 502 attrs: &item.attrs,
1b1a35ee 503 span: item.span,
dc9dc135 504 vis: &item.vis,
1a4d82fc
JJ
505 };
506 om.statics.push(s);
dfeec247
XL
507 }
508 hir::ItemKind::Const(type_, expr) => {
509 // Underscore constants do not correspond to a nameable item and
510 // so are never useful in documentation.
511 if ident.name != kw::Underscore {
512 let s = Constant {
513 type_,
514 expr,
515 id: item.hir_id,
516 name: ident.name,
517 attrs: &item.attrs,
1b1a35ee 518 span: item.span,
dfeec247
XL
519 vis: &item.vis,
520 };
521 om.constants.push(s);
522 }
523 }
dc9dc135 524 hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
dfeec247 525 let items = item_ids.iter().map(|ti| self.cx.tcx.hir().trait_item(ti.id)).collect();
1a4d82fc 526 let t = Trait {
2c00a5a8 527 is_auto,
3b2f2976 528 unsafety,
0731742a 529 name: ident.name,
3b2f2976 530 items,
dc9dc135
XL
531 generics,
532 bounds,
532ac7d7 533 id: item.hir_id,
dc9dc135 534 attrs: &item.attrs,
1b1a35ee 535 span: item.span,
dc9dc135 536 vis: &item.vis,
1a4d82fc
JJ
537 };
538 om.traits.push(t);
dfeec247 539 }
dc9dc135 540 hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
9fa01778
XL
541 let t = TraitAlias {
542 name: ident.name,
dc9dc135
XL
543 generics,
544 bounds,
532ac7d7 545 id: item.hir_id,
dc9dc135 546 attrs: &item.attrs,
1b1a35ee 547 span: item.span,
dc9dc135 548 vis: &item.vis,
9fa01778
XL
549 };
550 om.trait_aliases.push(t);
dfeec247
XL
551 }
552
553 hir::ItemKind::Impl {
554 unsafety,
555 polarity,
556 defaultness,
557 constness,
ba9703b0 558 defaultness_span: _,
dfeec247
XL
559 ref generics,
560 ref of_trait,
561 self_ty,
562 ref items,
563 } => {
0bf4aa26
XL
564 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
565 // them up regardless of where they're located.
dfeec247
XL
566 if !self.inlining && of_trait.is_none() {
567 let items =
568 items.iter().map(|item| self.cx.tcx.hir().impl_item(item.id)).collect();
476ff2be 569 let i = Impl {
3b2f2976
XL
570 unsafety,
571 polarity,
572 defaultness,
dfeec247 573 constness,
dc9dc135 574 generics,
dfeec247
XL
575 trait_: of_trait,
576 for_: self_ty,
3b2f2976 577 items,
dc9dc135 578 attrs: &item.attrs,
532ac7d7 579 id: item.hir_id,
1b1a35ee 580 span: item.span,
dc9dc135 581 vis: &item.vis,
476ff2be 582 };
9346a6ac
AL
583 om.impls.push(i);
584 }
dfeec247 585 }
1a4d82fc
JJ
586 }
587 }
588
dfeec247
XL
589 fn visit_foreign_item(
590 &mut self,
f035d41b 591 item: &'tcx hir::ForeignItem<'_>,
f9f354fc 592 renamed: Option<Ident>,
dfeec247
XL
593 om: &mut Module<'tcx>,
594 ) {
dc9dc135
XL
595 // If inlining we only want to include public functions.
596 if self.inlining && !item.vis.node.is_pub() {
597 return;
598 }
599
600 om.foreigns.push(ForeignItem {
601 id: item.hir_id,
602 name: renamed.unwrap_or(item.ident).name,
e74abb32 603 kind: &item.kind,
dc9dc135 604 vis: &item.vis,
dc9dc135 605 attrs: &item.attrs,
1b1a35ee 606 span: item.span,
dc9dc135
XL
607 });
608 }
609
0731742a 610 // Convert each `exported_macro` into a doc item.
f035d41b
XL
611 fn visit_local_macro(
612 &self,
613 def: &'tcx hir::MacroDef<'_>,
614 renamed: Option<Symbol>,
615 ) -> Macro<'tcx> {
ba9703b0
XL
616 debug!("visit_local_macro: {}", def.ident);
617 let tts = def.ast.body.inner_tokens().trees().collect::<Vec<_>>();
92a42be0 618 // Extract the spans of all matchers. They represent the "interface" of the macro.
8bb4bdeb 619 let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect();
92a42be0 620
1a4d82fc 621 Macro {
416331ca 622 hid: def.hir_id,
f9f354fc 623 def_id: self.cx.tcx.hir().local_def_id(def.hir_id).to_def_id(),
dc9dc135 624 attrs: &def.attrs,
ba9703b0 625 name: renamed.unwrap_or(def.ident.name),
1b1a35ee 626 span: def.span,
3b2f2976 627 matchers,
32a655c1 628 imported_from: None,
1a4d82fc
JJ
629 }
630 }
631}