Skip to content

Commit 7ac48d7

Browse files
committed
Resolve foreign macros
1 parent d6dd902 commit 7ac48d7

File tree

5 files changed

+84
-34
lines changed

5 files changed

+84
-34
lines changed

src/librustc_resolve/macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ impl<'a> Resolver<'a> {
409409
def
410410
}
411411

412-
fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
412+
pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
413413
kind: MacroKind, force: bool)
414414
-> Result<Def, Determinacy> {
415415
let ast::Path { ref segments, span } = *path;

src/librustdoc/clean/inline.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
135135
None
136136
}
137137
});
138-
let fqn = once(crate_name).chain(relative).collect();
138+
let fqn = if let clean::TypeKind::Macro = kind {
139+
vec![crate_name, relative.last().unwrap()]
140+
} else {
141+
once(crate_name).chain(relative).collect()
142+
};
139143
cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
140144
}
141145

src/librustdoc/clean/mod.rs

+76-31
Original file line numberDiff line numberDiff line change
@@ -824,34 +824,43 @@ impl AttributesExt for Attributes {
824824
}
825825
}
826826

827+
enum PathKind {
828+
/// can be either value or type, not a macro
829+
Unknown,
830+
/// macro
831+
Macro,
832+
/// values, functions, consts, statics, everything in the value namespace
833+
Value,
834+
/// types, traits, everything in the type namespace
835+
Type
836+
}
827837
impl Clean<Attributes> for [ast::Attribute] {
828838
fn clean(&self, cx: &DocContext) -> Attributes {
829839
let mut attrs = Attributes::from_ast(cx.sess().diagnostic(), self);
830840

831841
if UnstableFeatures::from_environment().is_nightly_build() {
832842
let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new);
833843
for link in markdown_links(&dox, cx.render_type) {
834-
let path = {
835-
let is_value;
844+
let def = {
845+
let mut kind = PathKind::Unknown;
836846
let path_str = if let Some(prefix) =
837847
["struct", "enum", "type",
838848
"trait", "union"].iter()
839849
.find(|p| link.starts_with(**p)) {
840-
is_value = Some(false);
850+
kind = PathKind::Type;
841851
link.trim_left_matches(prefix).trim()
842852
} else if let Some(prefix) =
843853
["const", "static"].iter()
844854
.find(|p| link.starts_with(**p)) {
845-
is_value = Some(true);
855+
kind = PathKind::Value;
846856
link.trim_left_matches(prefix).trim()
847857
} else if link.ends_with("()") {
848-
is_value = Some(true);
858+
kind = PathKind::Value;
849859
link.trim_right_matches("()").trim()
850-
} else if link.ends_with("!") {
851-
// FIXME (misdreavus): macros are resolved with different machinery
852-
continue;
860+
} else if link.ends_with('!') {
861+
kind = PathKind::Macro;
862+
link.trim_right_matches('!').trim()
853863
} else {
854-
is_value = None;
855864
link.trim()
856865
};
857866

@@ -879,34 +888,68 @@ impl Clean<Attributes> for [ast::Attribute] {
879888
}
880889
};
881890

882-
if let Some(is_value) = is_value {
883-
if let Ok(path) = resolve(is_value) {
884-
path
885-
} else {
886-
// this could just be a normal link or a broken link
887-
// we could potentially check if something is
888-
// "intra-doc-link-like" and warn in that case
889-
continue;
891+
match kind {
892+
PathKind::Value => {
893+
if let Ok(path) = resolve(true) {
894+
path.def
895+
} else {
896+
// this could just be a normal link or a broken link
897+
// we could potentially check if something is
898+
// "intra-doc-link-like" and warn in that case
899+
continue;
900+
}
890901
}
891-
} else {
892-
// try both!
893-
// It is imperative we search for not-a-value first
894-
// Otherwise we will find struct ctors for when we are looking
895-
// for structs, etc, and the link won't work.
896-
if let Ok(path) = resolve(false) {
897-
path
898-
} else if let Ok(path) = resolve(true) {
899-
path
900-
} else {
901-
// this could just be a normal link
902-
continue;
902+
PathKind::Type => {
903+
if let Ok(path) = resolve(false) {
904+
path.def
905+
} else {
906+
// this could just be a normal link
907+
continue;
908+
}
909+
}
910+
PathKind::Unknown => {
911+
// try both!
912+
// It is imperative we search for not-a-value first
913+
// Otherwise we will find struct ctors for when we are looking
914+
// for structs, etc, and the link won't work.
915+
if let Ok(path) = resolve(false) {
916+
path.def
917+
} else if let Ok(path) = resolve(true) {
918+
path.def
919+
} else {
920+
// this could just be a normal link
921+
continue;
922+
}
923+
}
924+
PathKind::Macro => {
925+
use syntax::ext::base::MacroKind;
926+
use syntax::ext::hygiene::Mark;
927+
let segment = ast::PathSegment {
928+
identifier: ast::Ident::from_str(path_str),
929+
span: DUMMY_SP,
930+
parameters: None,
931+
};
932+
let path = ast::Path {
933+
span: DUMMY_SP,
934+
segments: vec![segment],
935+
};
936+
937+
let mut resolver = cx.resolver.borrow_mut();
938+
let mark = Mark::root();
939+
let res = resolver
940+
.resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false);
941+
if let Ok(def) = res {
942+
def
943+
} else {
944+
continue;
945+
}
903946
}
904947
}
905948
};
906949

907-
register_def(cx, def);
908950

909-
attrs.links.push((link, path.def.def_id()));
951+
register_def(cx, def);
952+
attrs.links.push((link, def.def_id()));
910953
}
911954

912955
cx.sess().abort_if_errors();
@@ -1970,6 +2013,7 @@ pub enum TypeKind {
19702013
Variant,
19712014
Typedef,
19722015
Foreign,
2016+
Macro,
19732017
}
19742018

19752019
pub trait GetDefId {
@@ -3271,6 +3315,7 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
32713315
Def::TyForeign(i) => (i, TypeKind::Foreign),
32723316
Def::Static(i, _) => (i, TypeKind::Static),
32733317
Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
3318+
Def::Macro(i, _) => (i, TypeKind::Macro),
32743319
Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
32753320
Def::SelfTy(_, Some(impl_def_id)) => {
32763321
return impl_def_id

src/librustdoc/html/item_type.rs

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ impl From<clean::TypeKind> for ItemType {
102102
clean::TypeKind::Variant => ItemType::Variant,
103103
clean::TypeKind::Typedef => ItemType::Typedef,
104104
clean::TypeKind::Foreign => ItemType::ForeignType,
105+
clean::TypeKind::Macro => ItemType::Macro,
105106
}
106107
}
107108
}

src/librustdoc/html/render.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,7 @@ impl DocFolder for Cache {
12841284
clean::FunctionItem(..) | clean::ModuleItem(..) |
12851285
clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) |
12861286
clean::ConstantItem(..) | clean::StaticItem(..) |
1287-
clean::UnionItem(..) | clean::ForeignTypeItem
1287+
clean::UnionItem(..) | clean::ForeignTypeItem | clean::MacroItem(..)
12881288
if !self.stripped_mod => {
12891289
// Re-exported items mean that the same id can show up twice
12901290
// in the rustdoc ast that we're looking at. We know,

0 commit comments

Comments
 (0)