]> git.lizzy.rs Git - rust.git/commitdiff
intra-doc macro resolution should also handle proc macros
authorManish Goregaokar <manishsmail@gmail.com>
Tue, 9 Jun 2020 19:59:15 +0000 (12:59 -0700)
committerManish Goregaokar <manishsmail@gmail.com>
Tue, 9 Jun 2020 23:35:59 +0000 (16:35 -0700)
src/librustdoc/passes/collect_intra_doc_links.rs

index 149480ec80f2960a81073c1e16ffe8c72c4aad42..4514a616bd85638d395445f81ab7649a82d8a8cc 100644 (file)
@@ -122,6 +122,42 @@ fn variant_field(
         }
     }
 
+    /// Resolves a string as a macro.
+    fn macro_resolve(&self, path_str: &str, parent_id: Option<hir::HirId>) -> Option<Res> {
+        let cx = self.cx;
+        let path = ast::Path::from_ident(Ident::from_str(path_str));
+        cx.enter_resolver(|resolver| {
+            if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
+                &path,
+                None,
+                &ParentScope::module(resolver.graph_root()),
+                false,
+                false,
+            ) {
+                if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
+                    return Some(res.map_id(|_| panic!("unexpected id")));
+                }
+            }
+            if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
+                return Some(res.map_id(|_| panic!("unexpected id")));
+            }
+            if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) {
+                let module_id = cx.tcx.hir().local_def_id(module_id);
+                if let Ok((_, res)) =
+                    resolver.resolve_str_path_error(DUMMY_SP, path_str, MacroNS, module_id)
+                {
+                    // don't resolve builtins like `#[derive]`
+                    if let Res::Def(..) = res {
+                        let res = res.map_id(|_| panic!("unexpected node_id"));
+                        return Some(res);
+                    }
+                }
+            } else {
+                debug!("attempting to resolve item without parent module: {}", path_str);
+            }
+            None
+        })
+    }
     /// Resolves a string as a path within a particular namespace. Also returns an optional
     /// URL fragment in the case of variants and methods.
     fn resolve(
@@ -615,7 +651,8 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                     None => {
                         // Try everything!
                         let candidates = PerNS {
-                            macro_ns: macro_resolve(cx, path_str)
+                            macro_ns: self
+                                .macro_resolve(path_str, base_node)
                                 .map(|res| (res, extra_fragment.clone())),
                             type_ns: match self.resolve(
                                 path_str,
@@ -684,7 +721,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         }
                     }
                     Some(MacroNS) => {
-                        if let Some(res) = macro_resolve(cx, path_str) {
+                        if let Some(res) = self.macro_resolve(path_str, base_node) {
                             (res, extra_fragment)
                         } else {
                             resolution_failure(cx, &item, path_str, &dox, link_range);
@@ -727,28 +764,6 @@ fn fold_crate(&mut self, mut c: Crate) -> Crate {
     }
 }
 
-/// Resolves a string as a macro.
-fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
-    let path = ast::Path::from_ident(Ident::from_str(path_str));
-    cx.enter_resolver(|resolver| {
-        if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
-            &path,
-            None,
-            &ParentScope::module(resolver.graph_root()),
-            false,
-            false,
-        ) {
-            if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
-                return Some(res.map_id(|_| panic!("unexpected id")));
-            }
-        }
-        if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
-            return Some(res.map_id(|_| panic!("unexpected id")));
-        }
-        None
-    })
-}
-
 fn build_diagnostic(
     cx: &DocContext<'_>,
     item: &Item,