Restructure add_item_to_search_index
to eliminate code paths
Many of the code paths it handled were actually impossible. In other cases, the various checks and transformations were spread around in such a way that it was hard to tell what was going on.
This commit is contained in:
parent
08f4d54ea9
commit
220c2d8c9b
@ -442,7 +442,9 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) {
|
fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) {
|
||||||
let ((parent_did, parent_path), is_impl_child) = match *item.kind {
|
// Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl).
|
||||||
|
let item_def_id = item.item_id.as_def_id().unwrap();
|
||||||
|
let (parent_did, parent_path) = match *item.kind {
|
||||||
clean::StrippedItem(..) => return,
|
clean::StrippedItem(..) => return,
|
||||||
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
|
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
|
||||||
if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) =>
|
if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) =>
|
||||||
@ -454,123 +456,114 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
|
|||||||
| clean::TyAssocConstItem(..)
|
| clean::TyAssocConstItem(..)
|
||||||
| clean::TyAssocTypeItem(..)
|
| clean::TyAssocTypeItem(..)
|
||||||
| clean::StructFieldItem(..)
|
| clean::StructFieldItem(..)
|
||||||
| clean::VariantItem(..) => (
|
| clean::VariantItem(..) => {
|
||||||
(
|
// Don't index if containing module is stripped (i.e., private),
|
||||||
Some(
|
// or if item is tuple struct/variant field (name is a number -> not useful for search).
|
||||||
cache
|
if cache.stripped_mod
|
||||||
.parent_stack
|
|| item.type_() == ItemType::StructField
|
||||||
.last()
|
&& name.as_str().chars().all(|c| c.is_digit(10))
|
||||||
.expect("parent_stack is empty")
|
{
|
||||||
.item_id()
|
return;
|
||||||
.expect_def_id(),
|
}
|
||||||
),
|
let parent_did =
|
||||||
Some(&cache.stack[..cache.stack.len() - 1]),
|
cache.parent_stack.last().expect("parent_stack is empty").item_id().expect_def_id();
|
||||||
),
|
let parent_path = &cache.stack[..cache.stack.len() - 1];
|
||||||
false,
|
(Some(parent_did), parent_path)
|
||||||
),
|
}
|
||||||
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
|
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
|
||||||
let last = cache.parent_stack.last().expect("parent_stack is empty 2");
|
let last = cache.parent_stack.last().expect("parent_stack is empty 2");
|
||||||
let did = match &*last {
|
let parent_did = match &*last {
|
||||||
ParentStackItem::Impl {
|
// impl Trait for &T { fn method(self); }
|
||||||
// impl Trait for &T { fn method(self); }
|
//
|
||||||
//
|
// When generating a function index with the above shape, we want it
|
||||||
// When generating a function index with the above shape, we want it
|
// associated with `T`, not with the primitive reference type. It should
|
||||||
// associated with `T`, not with the primitive reference type. It should
|
// show up as `T::method`, rather than `reference::method`, in the search
|
||||||
// show up as `T::method`, rather than `reference::method`, in the search
|
// results page.
|
||||||
// results page.
|
ParentStackItem::Impl { for_: clean::Type::BorrowedRef { type_, .. }, .. } => {
|
||||||
for_: clean::Type::BorrowedRef { type_, .. },
|
type_.def_id(&cache)
|
||||||
..
|
}
|
||||||
} => type_.def_id(&cache),
|
|
||||||
ParentStackItem::Impl { for_, .. } => for_.def_id(&cache),
|
ParentStackItem::Impl { for_, .. } => for_.def_id(&cache),
|
||||||
ParentStackItem::Type(item_id) => item_id.as_def_id(),
|
ParentStackItem::Type(item_id) => item_id.as_def_id(),
|
||||||
};
|
};
|
||||||
let path = did
|
let Some(parent_did) = parent_did else { return };
|
||||||
.and_then(|did| cache.paths.get(&did))
|
// The current stack not necessarily has correlation
|
||||||
// The current stack not necessarily has correlation
|
// for where the type was defined. On the other
|
||||||
// for where the type was defined. On the other
|
// hand, `paths` always has the right
|
||||||
// hand, `paths` always has the right
|
// information if present.
|
||||||
// information if present.
|
match cache.paths.get(&parent_did) {
|
||||||
.map(|(fqp, _)| &fqp[..fqp.len() - 1]);
|
Some((fqp, _)) => (Some(parent_did), &fqp[..fqp.len() - 1]),
|
||||||
((did, path), true)
|
None => {
|
||||||
|
handle_orphan_impl_child(cache, item, parent_did);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Don't index if item is crate root, which is inserted later on when serializing the index.
|
||||||
|
if item_def_id.is_crate_root() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(None, &*cache.stack)
|
||||||
}
|
}
|
||||||
_ => ((None, Some(&*cache.stack)), false),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(parent_did) = parent_did
|
debug_assert!(!item.is_stripped());
|
||||||
&& parent_path.is_none()
|
|
||||||
&& is_impl_child
|
|
||||||
{
|
|
||||||
// We have a parent, but we don't know where they're
|
|
||||||
// defined yet. Wait for later to index this item.
|
|
||||||
let impl_generics = clean_impl_generics(cache.parent_stack.last());
|
|
||||||
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last()
|
|
||||||
{
|
|
||||||
item_id.as_def_id()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let orphan_item =
|
|
||||||
OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id };
|
|
||||||
cache.orphan_impl_items.push(orphan_item);
|
|
||||||
} else if let Some(path) = parent_path
|
|
||||||
&& (is_impl_child || !cache.stripped_mod)
|
|
||||||
{
|
|
||||||
debug_assert!(!item.is_stripped());
|
|
||||||
|
|
||||||
// A crate has a module at its root, containing all items,
|
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
|
||||||
// which should not be indexed. The crate-item itself is
|
// For searching purposes, a re-export is a duplicate if:
|
||||||
// inserted later on when serializing the search-index.
|
//
|
||||||
if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root())
|
// - It's either an inline, or a true re-export
|
||||||
&& let ty = item.type_()
|
// - It's got the same name
|
||||||
&& (ty != ItemType::StructField || u16::from_str_radix(name.as_str(), 10).is_err())
|
// - Both of them have the same exact path
|
||||||
{
|
let defid = match &*item.kind {
|
||||||
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
|
clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id),
|
||||||
// For searching purposes, a re-export is a duplicate if:
|
_ => item_def_id,
|
||||||
//
|
};
|
||||||
// - It's either an inline, or a true re-export
|
let path = join_with_double_colon(parent_path);
|
||||||
// - It's got the same name
|
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
|
||||||
// - Both of them have the same exact path
|
item_id.as_def_id()
|
||||||
let defid = (match &*item.kind {
|
} else {
|
||||||
&clean::ItemKind::ImportItem(ref import) => import.source.did,
|
None
|
||||||
_ => None,
|
};
|
||||||
})
|
let search_type = get_function_type_for_search(
|
||||||
.or_else(|| item.item_id.as_def_id());
|
&item,
|
||||||
// In case this is a field from a tuple struct, we don't add it into
|
tcx,
|
||||||
// the search index because its name is something like "0", which is
|
clean_impl_generics(cache.parent_stack.last()).as_ref(),
|
||||||
// not useful for rustdoc search.
|
parent_did,
|
||||||
let path = join_with_double_colon(path);
|
cache,
|
||||||
let impl_id =
|
);
|
||||||
if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
|
let aliases = item.attrs.get_doc_aliases();
|
||||||
item_id.as_def_id()
|
let deprecation = item.deprecation(tcx);
|
||||||
} else {
|
let index_item = IndexItem {
|
||||||
None
|
ty: item.type_(),
|
||||||
};
|
defid: Some(defid),
|
||||||
let search_type = get_function_type_for_search(
|
name,
|
||||||
&item,
|
path,
|
||||||
tcx,
|
desc,
|
||||||
clean_impl_generics(cache.parent_stack.last()).as_ref(),
|
parent: parent_did,
|
||||||
parent_did,
|
parent_idx: None,
|
||||||
cache,
|
exact_path: None,
|
||||||
);
|
impl_id,
|
||||||
let aliases = item.attrs.get_doc_aliases();
|
search_type,
|
||||||
let deprecation = item.deprecation(tcx);
|
aliases,
|
||||||
let index_item = IndexItem {
|
deprecation,
|
||||||
ty,
|
};
|
||||||
defid,
|
cache.search_index.push(index_item);
|
||||||
name,
|
}
|
||||||
path,
|
|
||||||
desc,
|
/// We have a parent, but we don't know where they're
|
||||||
parent: parent_did,
|
/// defined yet. Wait for later to index this item.
|
||||||
parent_idx: None,
|
/// See [`Cache::orphan_impl_items`].
|
||||||
exact_path: None,
|
fn handle_orphan_impl_child(cache: &mut Cache, item: &clean::Item, parent_did: DefId) {
|
||||||
impl_id,
|
let impl_generics = clean_impl_generics(cache.parent_stack.last());
|
||||||
search_type,
|
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
|
||||||
aliases,
|
item_id.as_def_id()
|
||||||
deprecation,
|
} else {
|
||||||
};
|
None
|
||||||
cache.search_index.push(index_item);
|
};
|
||||||
}
|
let orphan_item =
|
||||||
}
|
OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id };
|
||||||
|
cache.orphan_impl_items.push(orphan_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct OrphanImplItem {
|
pub(crate) struct OrphanImplItem {
|
||||||
|
Loading…
Reference in New Issue
Block a user