mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #145898 - lolbinarycat:rustdoc-search-trait-parent, r=GuillaumeGomez,notriddle
If a trait item appears in rustdoc search, hide the corrosponding impl items fixes rust-lang/rust#138251 cc `@notriddle`
This commit is contained in:
@@ -32,7 +32,7 @@ ENV SCRIPT \
|
||||
python3 ../x.py clippy ci --stage 2 && \
|
||||
python3 ../x.py test --stage 1 core alloc std test proc_macro && \
|
||||
python3 ../x.py test --stage 1 src/tools/compiletest && \
|
||||
python3 ../x.py doc bootstrap && \
|
||||
python3 ../x.py doc bootstrap --stage 1 && \
|
||||
# Build both public and internal documentation.
|
||||
RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc compiler --stage 1 && \
|
||||
RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc library --stage 1 && \
|
||||
|
||||
@@ -146,6 +146,14 @@ pub(crate) fn new(document_private: bool, document_hidden: bool) -> Self {
|
||||
Cache { document_private, document_hidden, ..Cache::default() }
|
||||
}
|
||||
|
||||
fn parent_stack_last_impl_and_trait_id(&self) -> (Option<DefId>, Option<DefId>) {
|
||||
if let Some(ParentStackItem::Impl { item_id, trait_, .. }) = self.parent_stack.last() {
|
||||
(item_id.as_def_id(), trait_.as_ref().map(|tr| tr.def_id()))
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was
|
||||
/// in `krate` due to the data being moved into the `Cache`.
|
||||
pub(crate) fn populate(cx: &mut DocContext<'_>, mut krate: clean::Crate) -> clean::Crate {
|
||||
@@ -572,11 +580,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
|
||||
clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id),
|
||||
_ => item_def_id,
|
||||
};
|
||||
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
|
||||
item_id.as_def_id()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let (impl_id, trait_parent) = cache.parent_stack_last_impl_and_trait_id();
|
||||
let search_type = get_function_type_for_search(
|
||||
item,
|
||||
tcx,
|
||||
@@ -594,12 +598,15 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
|
||||
desc,
|
||||
parent: parent_did,
|
||||
parent_idx: None,
|
||||
trait_parent,
|
||||
trait_parent_idx: None,
|
||||
exact_module_path: None,
|
||||
impl_id,
|
||||
search_type,
|
||||
aliases,
|
||||
deprecation,
|
||||
};
|
||||
|
||||
cache.search_index.push(index_item);
|
||||
}
|
||||
|
||||
@@ -608,19 +615,21 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
|
||||
/// See [`Cache::orphan_impl_items`].
|
||||
fn handle_orphan_impl_child(cache: &mut Cache, item: &clean::Item, parent_did: DefId) {
|
||||
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 (impl_id, trait_parent) = cache.parent_stack_last_impl_and_trait_id();
|
||||
let orphan_item = OrphanImplItem {
|
||||
parent: parent_did,
|
||||
trait_parent,
|
||||
item: item.clone(),
|
||||
impl_generics,
|
||||
impl_id,
|
||||
};
|
||||
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) parent: DefId,
|
||||
pub(crate) impl_id: Option<DefId>,
|
||||
pub(crate) trait_parent: Option<DefId>,
|
||||
pub(crate) item: clean::Item,
|
||||
pub(crate) impl_generics: Option<(clean::Type, clean::Generics)>,
|
||||
}
|
||||
|
||||
@@ -134,6 +134,8 @@ pub(crate) struct IndexItem {
|
||||
pub(crate) desc: String,
|
||||
pub(crate) parent: Option<DefId>,
|
||||
pub(crate) parent_idx: Option<usize>,
|
||||
pub(crate) trait_parent: Option<DefId>,
|
||||
pub(crate) trait_parent_idx: Option<usize>,
|
||||
pub(crate) exact_module_path: Option<Vec<Symbol>>,
|
||||
pub(crate) impl_id: Option<DefId>,
|
||||
pub(crate) search_type: Option<IndexItemFunctionType>,
|
||||
|
||||
@@ -610,6 +610,7 @@ pub(crate) fn sort(self) -> SerializedSearchIndex {
|
||||
module_path,
|
||||
exact_module_path,
|
||||
parent,
|
||||
trait_parent,
|
||||
deprecated,
|
||||
associated_item_disambiguator,
|
||||
}| EntryData {
|
||||
@@ -619,6 +620,7 @@ pub(crate) fn sort(self) -> SerializedSearchIndex {
|
||||
exact_module_path: exact_module_path
|
||||
.and_then(|path_id| map.get(&path_id).copied()),
|
||||
parent: parent.and_then(|path_id| map.get(&path_id).copied()),
|
||||
trait_parent: trait_parent.and_then(|path_id| map.get(&path_id).copied()),
|
||||
deprecated: *deprecated,
|
||||
associated_item_disambiguator: associated_item_disambiguator.clone(),
|
||||
},
|
||||
@@ -900,6 +902,7 @@ struct EntryData {
|
||||
module_path: Option<usize>,
|
||||
exact_module_path: Option<usize>,
|
||||
parent: Option<usize>,
|
||||
trait_parent: Option<usize>,
|
||||
deprecated: bool,
|
||||
associated_item_disambiguator: Option<String>,
|
||||
}
|
||||
@@ -915,6 +918,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
seq.serialize_element(&self.module_path.map(|id| id + 1).unwrap_or(0))?;
|
||||
seq.serialize_element(&self.exact_module_path.map(|id| id + 1).unwrap_or(0))?;
|
||||
seq.serialize_element(&self.parent.map(|id| id + 1).unwrap_or(0))?;
|
||||
seq.serialize_element(&self.trait_parent.map(|id| id + 1).unwrap_or(0))?;
|
||||
seq.serialize_element(&if self.deprecated { 1 } else { 0 })?;
|
||||
if let Some(disambig) = &self.associated_item_disambiguator {
|
||||
seq.serialize_element(&disambig)?;
|
||||
@@ -946,6 +950,9 @@ fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<EntryData, A::Erro
|
||||
.ok_or_else(|| A::Error::missing_field("exact_module_path"))?;
|
||||
let parent: SerializedOptional32 =
|
||||
v.next_element()?.ok_or_else(|| A::Error::missing_field("parent"))?;
|
||||
let trait_parent: SerializedOptional32 =
|
||||
v.next_element()?.ok_or_else(|| A::Error::missing_field("trait_parent"))?;
|
||||
|
||||
let deprecated: u32 = v.next_element()?.unwrap_or(0);
|
||||
let associated_item_disambiguator: Option<String> = v.next_element()?;
|
||||
Ok(EntryData {
|
||||
@@ -955,6 +962,7 @@ fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<EntryData, A::Erro
|
||||
exact_module_path: Option::<i32>::from(exact_module_path)
|
||||
.map(|path| path as usize),
|
||||
parent: Option::<i32>::from(parent).map(|path| path as usize),
|
||||
trait_parent: Option::<i32>::from(trait_parent).map(|path| path as usize),
|
||||
deprecated: deprecated != 0,
|
||||
associated_item_disambiguator,
|
||||
})
|
||||
@@ -1305,7 +1313,8 @@ pub(crate) fn build_index(
|
||||
|
||||
// Attach all orphan items to the type's definition if the type
|
||||
// has since been learned.
|
||||
for &OrphanImplItem { impl_id, parent, ref item, ref impl_generics } in &cache.orphan_impl_items
|
||||
for &OrphanImplItem { impl_id, parent, trait_parent, ref item, ref impl_generics } in
|
||||
&cache.orphan_impl_items
|
||||
{
|
||||
if let Some((fqp, _)) = cache.paths.get(&parent) {
|
||||
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
|
||||
@@ -1317,6 +1326,8 @@ pub(crate) fn build_index(
|
||||
desc,
|
||||
parent: Some(parent),
|
||||
parent_idx: None,
|
||||
trait_parent,
|
||||
trait_parent_idx: None,
|
||||
exact_module_path: None,
|
||||
impl_id,
|
||||
search_type: get_function_type_for_search(
|
||||
@@ -1421,6 +1432,7 @@ pub(crate) fn build_index(
|
||||
module_path: None,
|
||||
exact_module_path: None,
|
||||
parent: None,
|
||||
trait_parent: None,
|
||||
deprecated: false,
|
||||
associated_item_disambiguator: None,
|
||||
}),
|
||||
@@ -1434,39 +1446,46 @@ pub(crate) fn build_index(
|
||||
}
|
||||
};
|
||||
|
||||
// First, populate associated item parents
|
||||
// First, populate associated item parents and trait parents
|
||||
let crate_items: Vec<&mut IndexItem> = search_index
|
||||
.iter_mut()
|
||||
.map(|item| {
|
||||
item.parent_idx = item.parent.and_then(|defid| {
|
||||
cache.paths.get(&defid).map(|&(ref fqp, ty)| {
|
||||
let pathid = serialized_index.names.len();
|
||||
match serialized_index.crate_paths_index.entry((ty, fqp.clone())) {
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(pathid);
|
||||
let (name, path) = fqp.split_last().unwrap();
|
||||
serialized_index.push_path(
|
||||
name.as_str().to_string(),
|
||||
PathData {
|
||||
ty,
|
||||
module_path: path.to_vec(),
|
||||
exact_module_path: if let Some(exact_path) =
|
||||
cache.exact_paths.get(&defid)
|
||||
&& let Some((name2, exact_path)) = exact_path.split_last()
|
||||
&& name == name2
|
||||
{
|
||||
Some(exact_path.to_vec())
|
||||
} else {
|
||||
None
|
||||
let mut defid_to_rowid = |defid, check_external: bool| {
|
||||
cache
|
||||
.paths
|
||||
.get(&defid)
|
||||
.or_else(|| check_external.then(|| cache.external_paths.get(&defid)).flatten())
|
||||
.map(|&(ref fqp, ty)| {
|
||||
let pathid = serialized_index.names.len();
|
||||
match serialized_index.crate_paths_index.entry((ty, fqp.clone())) {
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(pathid);
|
||||
let (name, path) = fqp.split_last().unwrap();
|
||||
serialized_index.push_path(
|
||||
name.as_str().to_string(),
|
||||
PathData {
|
||||
ty,
|
||||
module_path: path.to_vec(),
|
||||
exact_module_path: if let Some(exact_path) =
|
||||
cache.exact_paths.get(&defid)
|
||||
&& let Some((name2, exact_path)) =
|
||||
exact_path.split_last()
|
||||
&& name == name2
|
||||
{
|
||||
Some(exact_path.to_vec())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
usize::try_from(pathid).unwrap()
|
||||
);
|
||||
usize::try_from(pathid).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
})
|
||||
};
|
||||
item.parent_idx = item.parent.and_then(|p| defid_to_rowid(p, false));
|
||||
item.trait_parent_idx = item.trait_parent.and_then(|p| defid_to_rowid(p, true));
|
||||
|
||||
if let Some(defid) = item.defid
|
||||
&& item.parent_idx.is_none()
|
||||
@@ -1549,6 +1568,7 @@ pub(crate) fn build_index(
|
||||
EntryData {
|
||||
ty: item.ty,
|
||||
parent: item.parent_idx,
|
||||
trait_parent: item.trait_parent_idx,
|
||||
module_path,
|
||||
exact_module_path,
|
||||
deprecated: item.deprecation.is_some(),
|
||||
|
||||
+21
-1
@@ -241,6 +241,7 @@ declare namespace rustdoc {
|
||||
modulePath: number?,
|
||||
exactModulePath: number?,
|
||||
parent: number?,
|
||||
traitParent: number?,
|
||||
deprecated: boolean,
|
||||
associatedItemDisambiguator: string?,
|
||||
}
|
||||
@@ -291,9 +292,12 @@ declare namespace rustdoc {
|
||||
path: PathData?,
|
||||
functionData: FunctionData?,
|
||||
deprecated: boolean,
|
||||
parent: { path: PathData, name: string}?,
|
||||
parent: RowParent,
|
||||
traitParent: RowParent,
|
||||
}
|
||||
|
||||
type RowParent = { path: PathData, name: string } | null;
|
||||
|
||||
type ItemType = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|
||||
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
|
||||
21 | 22 | 23 | 24 | 25 | 26;
|
||||
@@ -316,7 +320,23 @@ declare namespace rustdoc {
|
||||
interface ResultObject {
|
||||
desc: Promise<string|null>,
|
||||
displayPath: string,
|
||||
/**
|
||||
* path to where the item was defined (not inlined),
|
||||
* then `|`, then the `ItemType` of the item.
|
||||
*
|
||||
* This is often a private path, so it should not be displayed,
|
||||
* but this allows us to use it to reliably deduplicate reexported and inlined items
|
||||
*/
|
||||
fullPath: string,
|
||||
/**
|
||||
* The `fullPath` of the corresponding item within a trait.
|
||||
* For example, for `File::read`, this would be `std::io::Read::read|12`
|
||||
*
|
||||
* This is used to hide items from trait impls when the trait itself is in the search results.
|
||||
*
|
||||
* `null` if the item is not from a trait impl block.
|
||||
*/
|
||||
traitPath: string | null,
|
||||
href: string,
|
||||
id: number,
|
||||
dist: number,
|
||||
|
||||
@@ -1076,6 +1076,34 @@ function isPathSeparator(c) {
|
||||
return c === ":" || c === " ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array and an ascending list of indices,
|
||||
* efficiently removes each index in the array.
|
||||
*
|
||||
* @template T
|
||||
* @param {Array<T>} a
|
||||
* @param {Array<number>} idxList
|
||||
*/
|
||||
function removeIdxListAsc(a, idxList) {
|
||||
if (idxList.length === 0) {
|
||||
return;
|
||||
}
|
||||
let removed = 0;
|
||||
let i = idxList[0];
|
||||
let nextToRemove = idxList[0];
|
||||
while (i < a.length - idxList.length) {
|
||||
while (i === nextToRemove && removed < idxList.length) {
|
||||
removed++;
|
||||
i++;
|
||||
nextToRemove = idxList[removed];
|
||||
}
|
||||
a[i] = a[i + removed];
|
||||
i++;
|
||||
}
|
||||
// truncate array
|
||||
a.length -= idxList.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
@@ -1598,6 +1626,7 @@ class DocSearch {
|
||||
* module_path,
|
||||
* exact_module_path,
|
||||
* parent,
|
||||
* trait_parent,
|
||||
* deprecated,
|
||||
* associated_item_disambiguator
|
||||
* @type {rustdoc.ArrayWithOptionals<[
|
||||
@@ -1607,6 +1636,7 @@ class DocSearch {
|
||||
* number,
|
||||
* number,
|
||||
* number,
|
||||
* number,
|
||||
* ], [string]>}
|
||||
*/
|
||||
const raw = JSON.parse(encoded);
|
||||
@@ -1616,8 +1646,9 @@ class DocSearch {
|
||||
modulePath: raw[2] === 0 ? null : raw[2] - 1,
|
||||
exactModulePath: raw[3] === 0 ? null : raw[3] - 1,
|
||||
parent: raw[4] === 0 ? null : raw[4] - 1,
|
||||
deprecated: raw[5] === 1 ? true : false,
|
||||
associatedItemDisambiguator: raw.length === 6 ? null : raw[6],
|
||||
traitParent: raw[5] === 0 ? null : raw[5] - 1,
|
||||
deprecated: raw[6] === 1 ? true : false,
|
||||
associatedItemDisambiguator: raw.length === 7 ? null : raw[7],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1853,14 +1884,25 @@ class DocSearch {
|
||||
if (!entry && !path) {
|
||||
return null;
|
||||
}
|
||||
/** @type {function("parent" | "traitParent"): Promise<rustdoc.RowParent>} */
|
||||
const buildParentLike = async field => {
|
||||
const [name, path] = entry !== null && entry[field] !== null ?
|
||||
await Promise.all([this.getName(entry[field]), this.getPathData(entry[field])]) :
|
||||
[null, null];
|
||||
if (name !== null && path !== null) {
|
||||
return { name, path };
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const [
|
||||
moduleName,
|
||||
modulePathData,
|
||||
exactModuleName,
|
||||
exactModulePathData,
|
||||
parentName,
|
||||
parentPath,
|
||||
crate,
|
||||
parent,
|
||||
traitParent,
|
||||
crateOrNull,
|
||||
] = await Promise.all([
|
||||
entry && entry.modulePath !== null ? this.getName(entry.modulePath) : null,
|
||||
entry && entry.modulePath !== null ? this.getPathData(entry.modulePath) : null,
|
||||
@@ -1870,14 +1912,11 @@ class DocSearch {
|
||||
entry && entry.exactModulePath !== null ?
|
||||
this.getPathData(entry.exactModulePath) :
|
||||
null,
|
||||
entry && entry.parent !== null ?
|
||||
this.getName(entry.parent) :
|
||||
null,
|
||||
entry && entry.parent !== null ?
|
||||
this.getPathData(entry.parent) :
|
||||
null,
|
||||
entry ? nonnull(await this.getName(entry.krate)) : "",
|
||||
buildParentLike("parent"),
|
||||
buildParentLike("traitParent"),
|
||||
entry ? this.getName(entry.krate) : "",
|
||||
]);
|
||||
const crate = crateOrNull === null ? "" : crateOrNull;
|
||||
const name = name_ === null ? "" : name_;
|
||||
const normalizedName = (name.indexOf("_") === -1 ?
|
||||
name :
|
||||
@@ -1886,6 +1925,7 @@ class DocSearch {
|
||||
(modulePathData.modulePath === "" ?
|
||||
moduleName :
|
||||
`${modulePathData.modulePath}::${moduleName}`);
|
||||
|
||||
return {
|
||||
id,
|
||||
crate,
|
||||
@@ -1901,9 +1941,8 @@ class DocSearch {
|
||||
path,
|
||||
functionData,
|
||||
deprecated: entry ? entry.deprecated : false,
|
||||
parent: parentName !== null && parentPath !== null ?
|
||||
{ name: parentName, path: parentPath } :
|
||||
null,
|
||||
parent,
|
||||
traitParent,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2101,11 +2140,12 @@ class DocSearch {
|
||||
|
||||
/**
|
||||
* @param {rustdoc.Row} item
|
||||
* @returns {[string, string, string]}
|
||||
* @returns {[string, string, string, string|null]}
|
||||
*/
|
||||
const buildHrefAndPath = item => {
|
||||
let displayPath;
|
||||
let href;
|
||||
let traitPath = null;
|
||||
const type = itemTypes[item.ty];
|
||||
const name = item.name;
|
||||
let path = item.modulePath;
|
||||
@@ -2163,7 +2203,11 @@ class DocSearch {
|
||||
href = this.rootPath + item.modulePath.replace(/::/g, "/") +
|
||||
"/" + type + "." + name + ".html";
|
||||
}
|
||||
return [displayPath, href, `${exactPath}::${name}`];
|
||||
if (item.traitParent) {
|
||||
const tparent = item.traitParent;
|
||||
traitPath = `${tparent.path.exactModulePath}::${tparent.name}::${name}`;
|
||||
}
|
||||
return [displayPath, href, `${exactPath}::${name}`, traitPath];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2598,8 +2642,14 @@ class DocSearch {
|
||||
* @returns {rustdoc.ResultObject[]}
|
||||
*/
|
||||
const transformResults = (results, typeInfo, duplicates) => {
|
||||
/** @type {rustdoc.ResultObject[]} */
|
||||
const out = [];
|
||||
|
||||
// if we match a trait-associated item, we want to go back and
|
||||
// remove all the items that are their equivalent but in an impl block.
|
||||
/** @type {Map<string, number[]>} */
|
||||
const traitImplIdxMap = new Map();
|
||||
|
||||
for (const result of results) {
|
||||
const item = result.item;
|
||||
if (item.id !== -1) {
|
||||
@@ -2630,17 +2680,35 @@ class DocSearch {
|
||||
item,
|
||||
displayPath: pathSplitter(res[0]),
|
||||
fullPath: "",
|
||||
traitPath: null,
|
||||
href: "",
|
||||
displayTypeSignature: null,
|
||||
}, result);
|
||||
|
||||
// unlike other items, methods have a different ty when they are
|
||||
// in an impl block vs a trait. want to normalize this away.
|
||||
let ty = obj.item.ty;
|
||||
if (ty === TY_TYMETHOD) {
|
||||
ty = TY_METHOD;
|
||||
}
|
||||
// To be sure than it some items aren't considered as duplicate.
|
||||
obj.fullPath = res[2] + "|" + obj.item.ty;
|
||||
obj.fullPath = res[2] + "|" + ty;
|
||||
if (res[3]) {
|
||||
// "tymethod" is never used on impl blocks
|
||||
// (this is the reason we need to normalize tymethod away).
|
||||
obj.traitPath = res[3] + "|" + obj.item.ty;
|
||||
}
|
||||
|
||||
if (duplicates.has(obj.fullPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we're showing something like `Iterator::next`,
|
||||
// we don't want to also show a bunch of `<SomeType as Iterator>::next`
|
||||
if (obj.traitPath && duplicates.has(obj.traitPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Exports are specifically not shown if the items they point at
|
||||
// are already in the results.
|
||||
if (obj.item.ty === TY_IMPORT && duplicates.has(res[2])) {
|
||||
@@ -2661,14 +2729,29 @@ class DocSearch {
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME: if the trait item matches but is cut off due to MAX_RESULTS,
|
||||
// this deduplication will not happen.
|
||||
obj.href = res[1];
|
||||
if (obj.traitPath) {
|
||||
let list = traitImplIdxMap.get(obj.traitPath);
|
||||
if (list === undefined) {
|
||||
list = [];
|
||||
}
|
||||
list.push(out.length);
|
||||
traitImplIdxMap.set(obj.traitPath, list);
|
||||
} else {
|
||||
const toRemoveList = traitImplIdxMap.get(obj.fullPath);
|
||||
if (toRemoveList) {
|
||||
removeIdxListAsc(out, toRemoveList);
|
||||
}
|
||||
traitImplIdxMap.delete(obj.fullPath);
|
||||
}
|
||||
out.push(obj);
|
||||
if (out.length >= MAX_RESULTS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ include: "utils.goml"
|
||||
define-function: (
|
||||
"check-search-color",
|
||||
[
|
||||
theme, count_color, desc_color, path_color, bottom_border_color, keyword_color,
|
||||
theme, count_color, path_color, bottom_border_color, keyword_color,
|
||||
struct_color, associatedtype_color, tymethod_color, method_color, structfield_color,
|
||||
structfield_hover_color, macro_color, fn_color, hover_path_color, hover_background,
|
||||
attribute_color, grey
|
||||
@@ -21,10 +21,6 @@ define-function: (
|
||||
{"color": |count_color|},
|
||||
ALL,
|
||||
)
|
||||
assert-css: (
|
||||
"//*[@class='desc'][normalize-space()='Just a normal struct.']",
|
||||
{"color": |desc_color|},
|
||||
)
|
||||
assert-css: (
|
||||
"//*[@class='result-name']//*[normalize-space()='test_docs::']",
|
||||
{"color": |path_color|},
|
||||
@@ -97,16 +93,6 @@ define-function: (
|
||||
ALL,
|
||||
)
|
||||
|
||||
// Checking color and background on hover.
|
||||
move-cursor-to: "//*[@class='desc'][normalize-space()='Just a normal struct.']"
|
||||
assert-css: (
|
||||
"//*[@class='result-name']//*[normalize-space()='test_docs::']",
|
||||
{"color": |hover_path_color|},
|
||||
)
|
||||
assert-css: (
|
||||
"//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a",
|
||||
{"color": |hover_path_color|, "background-color": |hover_background|},
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -157,7 +143,6 @@ show-text: true
|
||||
call-function: ("check-search-color", {
|
||||
"theme": "ayu",
|
||||
"count_color": "#888",
|
||||
"desc_color": "#c5c5c5",
|
||||
"path_color": "#0096cf",
|
||||
"bottom_border_color": "#aaa3",
|
||||
"keyword_color": "#39afd7",
|
||||
@@ -179,7 +164,6 @@ call-function: ("check-search-color", {
|
||||
call-function: ("check-search-color", {
|
||||
"theme": "dark",
|
||||
"count_color": "#888",
|
||||
"desc_color": "#ddd",
|
||||
"path_color": "#ddd",
|
||||
"bottom_border_color": "#aaa3",
|
||||
"keyword_color": "#d2991d",
|
||||
@@ -201,7 +185,6 @@ call-function: ("check-search-color", {
|
||||
call-function: ("check-search-color", {
|
||||
"theme": "light",
|
||||
"count_color": "#888",
|
||||
"desc_color": "#000",
|
||||
"path_color": "#000",
|
||||
"bottom_border_color": "#aaa3",
|
||||
"keyword_color": "#3873ad",
|
||||
@@ -226,12 +209,27 @@ call-function: ("perform-search", {"query": "thisisanalias"})
|
||||
|
||||
define-function: (
|
||||
"check-alias",
|
||||
[theme, alias, grey],
|
||||
[theme, alias, grey, desc_color, hover_path_color, hover_background],
|
||||
block {
|
||||
call-function: ("switch-theme", {"theme": |theme|})
|
||||
// Checking that the colors for the alias element are the ones expected.
|
||||
assert-css: (".result-name .path .alias", {"color": |alias|})
|
||||
assert-css: (".result-name .path .alias > .grey", {"color": |grey|})
|
||||
assert-css: (
|
||||
"//*[@class='desc'][normalize-space()='Just a normal enum.']",
|
||||
{"color": |desc_color|},
|
||||
)
|
||||
// Checking color and background on hover.
|
||||
move-cursor-to: "//*[@class='desc'][normalize-space()='Just a normal enum.']"
|
||||
assert-css: (
|
||||
"//*[@class='result-name']//*[normalize-space()='test_docs::']",
|
||||
{"color": |hover_path_color|},
|
||||
)
|
||||
assert-css: (
|
||||
"//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a",
|
||||
{"color": |hover_path_color|, "background-color": |hover_background|},
|
||||
)
|
||||
|
||||
},
|
||||
)
|
||||
|
||||
@@ -239,14 +237,23 @@ call-function: ("check-alias", {
|
||||
"theme": "ayu",
|
||||
"alias": "#c5c5c5",
|
||||
"grey": "#999",
|
||||
"desc_color": "#c5c5c5",
|
||||
"hover_path_color": "#fff",
|
||||
"hover_background": "#3c3c3c",
|
||||
})
|
||||
call-function: ("check-alias", {
|
||||
"theme": "dark",
|
||||
"alias": "#fff",
|
||||
"grey": "#ccc",
|
||||
"desc_color": "#ddd",
|
||||
"hover_path_color": "#ddd",
|
||||
"hover_background": "#616161",
|
||||
})
|
||||
call-function: ("check-alias", {
|
||||
"theme": "light",
|
||||
"alias": "#000",
|
||||
"grey": "#999",
|
||||
"desc_color": "#000",
|
||||
"hover_path_color": "#000",
|
||||
"hover_background": "#ccc",
|
||||
})
|
||||
|
||||
@@ -79,7 +79,7 @@ call-function: ("check-colors", {
|
||||
set-window-size: (851, 600)
|
||||
|
||||
// Check the size and count in tabs
|
||||
assert-text: ("#search-tabs > button:nth-child(1) > .count", " (27) ")
|
||||
assert-text: ("#search-tabs > button:nth-child(1) > .count", " (25) ")
|
||||
assert-text: ("#search-tabs > button:nth-child(2) > .count", " (7) ")
|
||||
assert-text: ("#search-tabs > button:nth-child(3) > .count", " (0) ")
|
||||
store-property: ("#search-tabs > button:nth-child(1)", {"offsetWidth": buttonWidth})
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Checks multiple things on the sidebar display (width of its elements, colors, etc).
|
||||
include: "utils.goml"
|
||||
// Disable animations so they don't mess up color assertions later.
|
||||
emulate-media-features: { "prefers-reduced-motion": "reduce" }
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
assert-property: (".sidebar", {"clientWidth": "199"})
|
||||
show-text: true
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
// ignore-order
|
||||
|
||||
const EXPECTED = {
|
||||
'query': 'RawFd::as_raw_fd',
|
||||
'query': 'method:RawFd::as_raw_fd',
|
||||
'others': [
|
||||
// Reproduction test for https://github.com/rust-lang/rust/issues/78724
|
||||
// Validate that type alias methods get the correct path.
|
||||
{ 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' },
|
||||
{ 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' },
|
||||
{ 'path': 'std::os::fd::RawFd', 'name': 'as_raw_fd' },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
// make sure quoted search works both for items and and without generics
|
||||
// ignore-order
|
||||
|
||||
const FILTER_CRATE = 'std';
|
||||
|
||||
const EXPECTED = {
|
||||
'query': '"error"',
|
||||
'query': '"result"',
|
||||
'others': [
|
||||
{ 'path': 'std', 'name': 'error' },
|
||||
{ 'path': 'std::fmt', 'name': 'Error' },
|
||||
{ 'path': 'std::io', 'name': 'Error' },
|
||||
{ 'path': 'std', 'name': 'result' },
|
||||
{ 'path': 'std::result', 'name': 'Result' },
|
||||
{ 'path': 'std::fmt', 'name': 'Result' },
|
||||
],
|
||||
'in_args': [
|
||||
{ 'path': 'std::fmt::Error', 'name': 'eq' },
|
||||
{ 'path': 'std::fmt::Error', 'name': 'cmp' },
|
||||
{ 'path': 'std::fmt::Error', 'name': 'partial_cmp' },
|
||||
|
||||
{ 'path': 'std::result::Result', 'name': 'branch' },
|
||||
{ 'path': 'std::result::Result', 'name': 'ok' },
|
||||
{ 'path': 'std::result::Result', 'name': 'unwrap' },
|
||||
],
|
||||
'returned': [
|
||||
{ 'path': 'std::fmt::LowerExp', 'name': 'fmt' },
|
||||
{ 'path': 'std::bool', 'name': 'try_into' },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// ignore-order
|
||||
// make sure type-based searches with traits get unboxed too
|
||||
|
||||
const EXPECTED = [
|
||||
{
|
||||
'query': 'bufread -> result<[u8]>',
|
||||
'query': 'any -> result<box>',
|
||||
'others': [
|
||||
{ 'path': 'std::boxed::Box', 'name': 'fill_buf' },
|
||||
{ 'path': 'std::boxed::Box', 'name': 'downcast' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -9,4 +9,24 @@ const EXPECTED = [
|
||||
{ 'path': 'trait_methods::MyTrait', 'name': 'next' },
|
||||
],
|
||||
},
|
||||
// the traitParent deduplication pass should remove
|
||||
// Empty::next, as it would be redundant
|
||||
{
|
||||
'query': 'next',
|
||||
'correction': null,
|
||||
'in_args': [],
|
||||
'others': [
|
||||
{ 'path': 'trait_methods::MyTrait', 'name': 'next' },
|
||||
],
|
||||
},
|
||||
// if the trait does not match, no deduplication happens
|
||||
{
|
||||
'query': '-> option<()>',
|
||||
'correction': null,
|
||||
'in_args': [],
|
||||
'others': [
|
||||
{ 'path': 'trait_methods::Empty', 'name': 'next' },
|
||||
{ 'path': 'trait_methods::Void', 'name': 'next' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -2,3 +2,21 @@ pub trait MyTrait {
|
||||
type Item;
|
||||
fn next(&mut self) -> Option<Self::Item>;
|
||||
}
|
||||
|
||||
pub struct Empty;
|
||||
|
||||
impl MyTrait for Empty {
|
||||
type Item = ();
|
||||
fn next(&mut self) -> Option<()> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Void;
|
||||
|
||||
impl MyTrait for Void {
|
||||
type Item = ();
|
||||
fn next(&mut self) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user