Refactor resolve_with_disambiguator
into a separate function
This commit is contained in:
parent
245f69ad3c
commit
7dc0d335bc
@ -998,169 +998,19 @@ impl LinkCollector<'_, '_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match disambiguator.map(Disambiguator::ns) {
|
match self.resolve_with_disambiguator(
|
||||||
Some(ns @ (ValueNS | TypeNS)) => {
|
disambiguator,
|
||||||
match self.resolve(path_str, ns, ¤t_item, base_node, &extra_fragment) {
|
item,
|
||||||
Ok(res) => res,
|
dox,
|
||||||
Err(ErrorKind::Resolve(box mut kind)) => {
|
path_str,
|
||||||
// We only looked in one namespace. Try to give a better error if possible.
|
current_item,
|
||||||
if kind.full_res().is_none() {
|
base_node,
|
||||||
let other_ns = if ns == ValueNS { TypeNS } else { ValueNS };
|
extra_fragment,
|
||||||
for &new_ns in &[other_ns, MacroNS] {
|
&ori_link,
|
||||||
if let Some(res) = self.check_full_res(
|
link_range.clone(),
|
||||||
new_ns,
|
) {
|
||||||
path_str,
|
Some(x) => x,
|
||||||
base_node,
|
None => return,
|
||||||
¤t_item,
|
|
||||||
&extra_fragment,
|
|
||||||
) {
|
|
||||||
kind = ResolutionFailure::WrongNamespace(res, ns);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolution_failure(
|
|
||||||
self,
|
|
||||||
&item,
|
|
||||||
path_str,
|
|
||||||
disambiguator,
|
|
||||||
dox,
|
|
||||||
link_range,
|
|
||||||
smallvec![kind],
|
|
||||||
);
|
|
||||||
// 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.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(ErrorKind::AnchorFailure(msg)) => {
|
|
||||||
anchor_failure(cx, &item, &ori_link, dox, link_range, msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// Try everything!
|
|
||||||
let mut candidates = PerNS {
|
|
||||||
macro_ns: self
|
|
||||||
.macro_resolve(path_str, base_node)
|
|
||||||
.map(|res| (res, extra_fragment.clone())),
|
|
||||||
type_ns: match self.resolve(
|
|
||||||
path_str,
|
|
||||||
TypeNS,
|
|
||||||
¤t_item,
|
|
||||||
base_node,
|
|
||||||
&extra_fragment,
|
|
||||||
) {
|
|
||||||
Ok(res) => {
|
|
||||||
debug!("got res in TypeNS: {:?}", res);
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
Err(ErrorKind::AnchorFailure(msg)) => {
|
|
||||||
anchor_failure(cx, &item, &ori_link, dox, link_range, msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(ErrorKind::Resolve(box kind)) => Err(kind),
|
|
||||||
},
|
|
||||||
value_ns: match self.resolve(
|
|
||||||
path_str,
|
|
||||||
ValueNS,
|
|
||||||
¤t_item,
|
|
||||||
base_node,
|
|
||||||
&extra_fragment,
|
|
||||||
) {
|
|
||||||
Ok(res) => Ok(res),
|
|
||||||
Err(ErrorKind::AnchorFailure(msg)) => {
|
|
||||||
anchor_failure(cx, &item, &ori_link, dox, link_range, msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(ErrorKind::Resolve(box kind)) => Err(kind),
|
|
||||||
}
|
|
||||||
.and_then(|(res, fragment)| {
|
|
||||||
// Constructors are picked up in the type namespace.
|
|
||||||
match res {
|
|
||||||
Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => {
|
|
||||||
Err(ResolutionFailure::WrongNamespace(res, TypeNS))
|
|
||||||
}
|
|
||||||
_ => match (fragment, extra_fragment) {
|
|
||||||
(Some(fragment), Some(_)) => {
|
|
||||||
// Shouldn't happen but who knows?
|
|
||||||
Ok((res, Some(fragment)))
|
|
||||||
}
|
|
||||||
(fragment, None) | (None, fragment) => Ok((res, fragment)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
let len = candidates.iter().filter(|res| res.is_ok()).count();
|
|
||||||
|
|
||||||
if len == 0 {
|
|
||||||
resolution_failure(
|
|
||||||
self,
|
|
||||||
&item,
|
|
||||||
path_str,
|
|
||||||
disambiguator,
|
|
||||||
dox,
|
|
||||||
link_range,
|
|
||||||
candidates.into_iter().filter_map(|res| res.err()).collect(),
|
|
||||||
);
|
|
||||||
// this could just be a normal link
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if len == 1 {
|
|
||||||
candidates.into_iter().filter_map(|res| res.ok()).next().unwrap()
|
|
||||||
} else if len == 2 && is_derive_trait_collision(&candidates) {
|
|
||||||
candidates.type_ns.unwrap()
|
|
||||||
} else {
|
|
||||||
if is_derive_trait_collision(&candidates) {
|
|
||||||
candidates.macro_ns = Err(ResolutionFailure::Dummy);
|
|
||||||
}
|
|
||||||
// If we're reporting an ambiguity, don't mention the namespaces that failed
|
|
||||||
let candidates =
|
|
||||||
candidates.map(|candidate| candidate.ok().map(|(res, _)| res));
|
|
||||||
ambiguity_error(
|
|
||||||
cx,
|
|
||||||
&item,
|
|
||||||
path_str,
|
|
||||||
dox,
|
|
||||||
link_range,
|
|
||||||
candidates.present_items().collect(),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(MacroNS) => {
|
|
||||||
match self.macro_resolve(path_str, base_node) {
|
|
||||||
Ok(res) => (res, extra_fragment),
|
|
||||||
Err(mut kind) => {
|
|
||||||
// `macro_resolve` only looks in the macro namespace. Try to give a better error if possible.
|
|
||||||
for &ns in &[TypeNS, ValueNS] {
|
|
||||||
if let Some(res) = self.check_full_res(
|
|
||||||
ns,
|
|
||||||
path_str,
|
|
||||||
base_node,
|
|
||||||
¤t_item,
|
|
||||||
&extra_fragment,
|
|
||||||
) {
|
|
||||||
kind = ResolutionFailure::WrongNamespace(res, MacroNS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolution_failure(
|
|
||||||
self,
|
|
||||||
&item,
|
|
||||||
path_str,
|
|
||||||
disambiguator,
|
|
||||||
dox,
|
|
||||||
link_range,
|
|
||||||
smallvec![kind],
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1274,6 +1124,183 @@ impl LinkCollector<'_, '_> {
|
|||||||
item.attrs.links.push(ItemLink { link: ori_link, link_text, did: Some(id), fragment });
|
item.attrs.links.push(ItemLink { link: ori_link, link_text, did: Some(id), fragment });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_with_disambiguator(
|
||||||
|
&self,
|
||||||
|
disambiguator: Option<Disambiguator>,
|
||||||
|
item: &mut Item,
|
||||||
|
dox: &str,
|
||||||
|
path_str: &str,
|
||||||
|
current_item: &Option<String>,
|
||||||
|
base_node: Option<DefId>,
|
||||||
|
extra_fragment: Option<String>,
|
||||||
|
ori_link: &str,
|
||||||
|
link_range: Option<Range<usize>>,
|
||||||
|
) -> Option<(Res, Option<String>)> {
|
||||||
|
match disambiguator.map(Disambiguator::ns) {
|
||||||
|
Some(ns @ (ValueNS | TypeNS)) => {
|
||||||
|
match self.resolve(path_str, ns, ¤t_item, base_node, &extra_fragment) {
|
||||||
|
Ok(res) => Some(res),
|
||||||
|
Err(ErrorKind::Resolve(box mut kind)) => {
|
||||||
|
// We only looked in one namespace. Try to give a better error if possible.
|
||||||
|
if kind.full_res().is_none() {
|
||||||
|
let other_ns = if ns == ValueNS { TypeNS } else { ValueNS };
|
||||||
|
for &new_ns in &[other_ns, MacroNS] {
|
||||||
|
if let Some(res) = self.check_full_res(
|
||||||
|
new_ns,
|
||||||
|
path_str,
|
||||||
|
base_node,
|
||||||
|
¤t_item,
|
||||||
|
&extra_fragment,
|
||||||
|
) {
|
||||||
|
kind = ResolutionFailure::WrongNamespace(res, ns);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolution_failure(
|
||||||
|
self,
|
||||||
|
&item,
|
||||||
|
path_str,
|
||||||
|
disambiguator,
|
||||||
|
dox,
|
||||||
|
link_range,
|
||||||
|
smallvec![kind],
|
||||||
|
);
|
||||||
|
// 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.
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Err(ErrorKind::AnchorFailure(msg)) => {
|
||||||
|
anchor_failure(self.cx, &item, &ori_link, dox, link_range, msg);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// Try everything!
|
||||||
|
let mut candidates = PerNS {
|
||||||
|
macro_ns: self
|
||||||
|
.macro_resolve(path_str, base_node)
|
||||||
|
.map(|res| (res, extra_fragment.clone())),
|
||||||
|
type_ns: match self.resolve(
|
||||||
|
path_str,
|
||||||
|
TypeNS,
|
||||||
|
¤t_item,
|
||||||
|
base_node,
|
||||||
|
&extra_fragment,
|
||||||
|
) {
|
||||||
|
Ok(res) => {
|
||||||
|
debug!("got res in TypeNS: {:?}", res);
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
Err(ErrorKind::AnchorFailure(msg)) => {
|
||||||
|
anchor_failure(self.cx, &item, ori_link, dox, link_range, msg);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Err(ErrorKind::Resolve(box kind)) => Err(kind),
|
||||||
|
},
|
||||||
|
value_ns: match self.resolve(
|
||||||
|
path_str,
|
||||||
|
ValueNS,
|
||||||
|
¤t_item,
|
||||||
|
base_node,
|
||||||
|
&extra_fragment,
|
||||||
|
) {
|
||||||
|
Ok(res) => Ok(res),
|
||||||
|
Err(ErrorKind::AnchorFailure(msg)) => {
|
||||||
|
anchor_failure(self.cx, &item, ori_link, dox, link_range, msg);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Err(ErrorKind::Resolve(box kind)) => Err(kind),
|
||||||
|
}
|
||||||
|
.and_then(|(res, fragment)| {
|
||||||
|
// Constructors are picked up in the type namespace.
|
||||||
|
match res {
|
||||||
|
Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => {
|
||||||
|
Err(ResolutionFailure::WrongNamespace(res, TypeNS))
|
||||||
|
}
|
||||||
|
_ => match (fragment, extra_fragment) {
|
||||||
|
(Some(fragment), Some(_)) => {
|
||||||
|
// Shouldn't happen but who knows?
|
||||||
|
Ok((res, Some(fragment)))
|
||||||
|
}
|
||||||
|
(fragment, None) | (None, fragment) => Ok((res, fragment)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
let len = candidates.iter().filter(|res| res.is_ok()).count();
|
||||||
|
|
||||||
|
if len == 0 {
|
||||||
|
resolution_failure(
|
||||||
|
self,
|
||||||
|
&item,
|
||||||
|
path_str,
|
||||||
|
disambiguator,
|
||||||
|
dox,
|
||||||
|
link_range,
|
||||||
|
candidates.into_iter().filter_map(|res| res.err()).collect(),
|
||||||
|
);
|
||||||
|
// this could just be a normal link
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if len == 1 {
|
||||||
|
Some(candidates.into_iter().filter_map(|res| res.ok()).next().unwrap())
|
||||||
|
} else if len == 2 && is_derive_trait_collision(&candidates) {
|
||||||
|
Some(candidates.type_ns.unwrap())
|
||||||
|
} else {
|
||||||
|
if is_derive_trait_collision(&candidates) {
|
||||||
|
candidates.macro_ns = Err(ResolutionFailure::Dummy);
|
||||||
|
}
|
||||||
|
// If we're reporting an ambiguity, don't mention the namespaces that failed
|
||||||
|
let candidates = candidates.map(|candidate| candidate.ok().map(|(res, _)| res));
|
||||||
|
ambiguity_error(
|
||||||
|
self.cx,
|
||||||
|
&item,
|
||||||
|
path_str,
|
||||||
|
dox,
|
||||||
|
link_range,
|
||||||
|
candidates.present_items().collect(),
|
||||||
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(MacroNS) => {
|
||||||
|
match self.macro_resolve(path_str, base_node) {
|
||||||
|
Ok(res) => Some((res, extra_fragment)),
|
||||||
|
Err(mut kind) => {
|
||||||
|
// `macro_resolve` only looks in the macro namespace. Try to give a better error if possible.
|
||||||
|
for &ns in &[TypeNS, ValueNS] {
|
||||||
|
if let Some(res) = self.check_full_res(
|
||||||
|
ns,
|
||||||
|
path_str,
|
||||||
|
base_node,
|
||||||
|
¤t_item,
|
||||||
|
&extra_fragment,
|
||||||
|
) {
|
||||||
|
kind = ResolutionFailure::WrongNamespace(res, MacroNS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolution_failure(
|
||||||
|
self,
|
||||||
|
&item,
|
||||||
|
path_str,
|
||||||
|
disambiguator,
|
||||||
|
dox,
|
||||||
|
link_range,
|
||||||
|
smallvec![kind],
|
||||||
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
Loading…
Reference in New Issue
Block a user