3 use rustc_hir::def::Namespace::TypeNS;
4 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
5 use rustc_interface::interface;
8 use std::cell::RefCell;
12 type Resolver = Rc<RefCell<interface::BoxedResolver>>;
13 // Letting the resolver escape at the end of the function leads to inconsistencies between the
14 // crates the TyCtxt sees and the resolver sees (because the resolver could load more crates
15 // after escaping). Hopefully `IntraLinkCrateLoader` gets all the crates we need ...
16 crate fn load_intra_link_crates(resolver: Resolver, krate: &ast::Crate) -> Resolver {
17 let mut loader = IntraLinkCrateLoader { current_mod: CRATE_DEF_ID, resolver };
18 // `walk_crate` doesn't visit the crate itself for some reason.
19 loader.load_links_in_attrs(&krate.attrs, krate.span);
20 visit::walk_crate(&mut loader, krate);
24 struct IntraLinkCrateLoader {
25 current_mod: LocalDefId,
26 resolver: Rc<RefCell<interface::BoxedResolver>>,
29 impl IntraLinkCrateLoader {
30 fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute], span: Span) {
31 use crate::html::markdown::markdown_links;
32 use crate::passes::collect_intra_doc_links::preprocess_link;
34 // FIXME: this probably needs to consider inlining
35 let attrs = crate::clean::Attributes::from_ast(attrs, None);
36 for (parent_module, doc) in attrs.collapsed_doc_value_by_module_level() {
38 for link in markdown_links(doc.as_str()) {
40 let path_str = if let Some(Ok(x)) = preprocess_link(&link) {
45 self.resolver.borrow_mut().access(|resolver| {
46 let _ = resolver.resolve_str_path_error(
50 parent_module.unwrap_or_else(|| self.current_mod.to_def_id()),
58 impl visit::Visitor<'_> for IntraLinkCrateLoader {
59 fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
60 self.load_links_in_attrs(&item.attrs, item.span);
61 visit::walk_foreign_item(self, item)
64 fn visit_item(&mut self, item: &ast::Item) {
65 use rustc_ast_lowering::ResolverAstLowering;
67 if let ast::ItemKind::Mod(..) = item.kind {
69 self.resolver.borrow_mut().access(|resolver| resolver.local_def_id(item.id));
70 let old_mod = mem::replace(&mut self.current_mod, new_mod);
72 self.load_links_in_attrs(&item.attrs, item.span);
73 visit::walk_item(self, item);
75 self.current_mod = old_mod;
77 self.load_links_in_attrs(&item.attrs, item.span);
78 visit::walk_item(self, item);
82 // NOTE: if doc-comments are ever allowed on function parameters, this will have to implement `visit_param` too.
84 fn visit_assoc_item(&mut self, item: &ast::AssocItem, ctxt: visit::AssocCtxt) {
85 self.load_links_in_attrs(&item.attrs, item.span);
86 visit::walk_assoc_item(self, item, ctxt)
89 fn visit_field_def(&mut self, field: &ast::FieldDef) {
90 self.load_links_in_attrs(&field.attrs, field.span);
91 visit::walk_field_def(self, field)
94 fn visit_variant(&mut self, v: &ast::Variant) {
95 self.load_links_in_attrs(&v.attrs, v.span);
96 visit::walk_variant(self, v)