Resolve foreign macros
This commit is contained in:
parent
d6dd902616
commit
7ac48d793b
@ -409,7 +409,7 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin
|
||||
def
|
||||
}
|
||||
|
||||
fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
|
||||
pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
|
||||
kind: MacroKind, force: bool)
|
||||
-> Result<Def, Determinacy> {
|
||||
let ast::Path { ref segments, span } = *path;
|
||||
|
@ -135,7 +135,11 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
|
||||
None
|
||||
}
|
||||
});
|
||||
let fqn = once(crate_name).chain(relative).collect();
|
||||
let fqn = if let clean::TypeKind::Macro = kind {
|
||||
vec![crate_name, relative.last().unwrap()]
|
||||
} else {
|
||||
once(crate_name).chain(relative).collect()
|
||||
};
|
||||
cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
|
||||
}
|
||||
|
||||
|
@ -824,6 +824,16 @@ fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
enum PathKind {
|
||||
/// can be either value or type, not a macro
|
||||
Unknown,
|
||||
/// macro
|
||||
Macro,
|
||||
/// values, functions, consts, statics, everything in the value namespace
|
||||
Value,
|
||||
/// types, traits, everything in the type namespace
|
||||
Type
|
||||
}
|
||||
impl Clean<Attributes> for [ast::Attribute] {
|
||||
fn clean(&self, cx: &DocContext) -> Attributes {
|
||||
let mut attrs = Attributes::from_ast(cx.sess().diagnostic(), self);
|
||||
@ -831,27 +841,26 @@ fn clean(&self, cx: &DocContext) -> Attributes {
|
||||
if UnstableFeatures::from_environment().is_nightly_build() {
|
||||
let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new);
|
||||
for link in markdown_links(&dox, cx.render_type) {
|
||||
let path = {
|
||||
let is_value;
|
||||
let def = {
|
||||
let mut kind = PathKind::Unknown;
|
||||
let path_str = if let Some(prefix) =
|
||||
["struct", "enum", "type",
|
||||
"trait", "union"].iter()
|
||||
.find(|p| link.starts_with(**p)) {
|
||||
is_value = Some(false);
|
||||
kind = PathKind::Type;
|
||||
link.trim_left_matches(prefix).trim()
|
||||
} else if let Some(prefix) =
|
||||
["const", "static"].iter()
|
||||
.find(|p| link.starts_with(**p)) {
|
||||
is_value = Some(true);
|
||||
kind = PathKind::Value;
|
||||
link.trim_left_matches(prefix).trim()
|
||||
} else if link.ends_with("()") {
|
||||
is_value = Some(true);
|
||||
kind = PathKind::Value;
|
||||
link.trim_right_matches("()").trim()
|
||||
} else if link.ends_with("!") {
|
||||
// FIXME (misdreavus): macros are resolved with different machinery
|
||||
continue;
|
||||
} else if link.ends_with('!') {
|
||||
kind = PathKind::Macro;
|
||||
link.trim_right_matches('!').trim()
|
||||
} else {
|
||||
is_value = None;
|
||||
link.trim()
|
||||
};
|
||||
|
||||
@ -879,34 +888,68 @@ fn clean(&self, cx: &DocContext) -> Attributes {
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(is_value) = is_value {
|
||||
if let Ok(path) = resolve(is_value) {
|
||||
path
|
||||
} else {
|
||||
// this could just be a normal link or a broken link
|
||||
// we could potentially check if something is
|
||||
// "intra-doc-link-like" and warn in that case
|
||||
continue;
|
||||
match kind {
|
||||
PathKind::Value => {
|
||||
if let Ok(path) = resolve(true) {
|
||||
path.def
|
||||
} else {
|
||||
// this could just be a normal link or a broken link
|
||||
// we could potentially check if something is
|
||||
// "intra-doc-link-like" and warn in that case
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// try both!
|
||||
// It is imperative we search for not-a-value first
|
||||
// Otherwise we will find struct ctors for when we are looking
|
||||
// for structs, etc, and the link won't work.
|
||||
if let Ok(path) = resolve(false) {
|
||||
path
|
||||
} else if let Ok(path) = resolve(true) {
|
||||
path
|
||||
} else {
|
||||
// this could just be a normal link
|
||||
continue;
|
||||
PathKind::Type => {
|
||||
if let Ok(path) = resolve(false) {
|
||||
path.def
|
||||
} else {
|
||||
// this could just be a normal link
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PathKind::Unknown => {
|
||||
// try both!
|
||||
// It is imperative we search for not-a-value first
|
||||
// Otherwise we will find struct ctors for when we are looking
|
||||
// for structs, etc, and the link won't work.
|
||||
if let Ok(path) = resolve(false) {
|
||||
path.def
|
||||
} else if let Ok(path) = resolve(true) {
|
||||
path.def
|
||||
} else {
|
||||
// this could just be a normal link
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PathKind::Macro => {
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::ext::hygiene::Mark;
|
||||
let segment = ast::PathSegment {
|
||||
identifier: ast::Ident::from_str(path_str),
|
||||
span: DUMMY_SP,
|
||||
parameters: None,
|
||||
};
|
||||
let path = ast::Path {
|
||||
span: DUMMY_SP,
|
||||
segments: vec![segment],
|
||||
};
|
||||
|
||||
let mut resolver = cx.resolver.borrow_mut();
|
||||
let mark = Mark::root();
|
||||
let res = resolver
|
||||
.resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false);
|
||||
if let Ok(def) = res {
|
||||
def
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
register_def(cx, def);
|
||||
|
||||
attrs.links.push((link, path.def.def_id()));
|
||||
register_def(cx, def);
|
||||
attrs.links.push((link, def.def_id()));
|
||||
}
|
||||
|
||||
cx.sess().abort_if_errors();
|
||||
@ -1970,6 +2013,7 @@ pub enum TypeKind {
|
||||
Variant,
|
||||
Typedef,
|
||||
Foreign,
|
||||
Macro,
|
||||
}
|
||||
|
||||
pub trait GetDefId {
|
||||
@ -3271,6 +3315,7 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
|
||||
Def::TyForeign(i) => (i, TypeKind::Foreign),
|
||||
Def::Static(i, _) => (i, TypeKind::Static),
|
||||
Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
|
||||
Def::Macro(i, _) => (i, TypeKind::Macro),
|
||||
Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
|
||||
Def::SelfTy(_, Some(impl_def_id)) => {
|
||||
return impl_def_id
|
||||
|
@ -102,6 +102,7 @@ fn from(kind: clean::TypeKind) -> ItemType {
|
||||
clean::TypeKind::Variant => ItemType::Variant,
|
||||
clean::TypeKind::Typedef => ItemType::Typedef,
|
||||
clean::TypeKind::Foreign => ItemType::ForeignType,
|
||||
clean::TypeKind::Macro => ItemType::Macro,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1284,7 +1284,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
|
||||
clean::FunctionItem(..) | clean::ModuleItem(..) |
|
||||
clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) |
|
||||
clean::ConstantItem(..) | clean::StaticItem(..) |
|
||||
clean::UnionItem(..) | clean::ForeignTypeItem
|
||||
clean::UnionItem(..) | clean::ForeignTypeItem | clean::MacroItem(..)
|
||||
if !self.stripped_mod => {
|
||||
// Re-exported items mean that the same id can show up twice
|
||||
// in the rustdoc ast that we're looking at. We know,
|
||||
|
Loading…
Reference in New Issue
Block a user