diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index e281139ca38ff..e3829603072b0 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -91,54 +91,55 @@ if (!Promise.withResolvers) { // ==================== Core search logic begin ==================== // This mapping table should match the discriminants of // `rustdoc::formats::item_type::ItemType` type in Rust. -const itemTypes = [ - "keyword", - "primitive", - "mod", - "externcrate", - "import", - "struct", // 5 - "enum", - "fn", - "type", - "static", - "trait", // 10 - "impl", - "tymethod", - "method", - "structfield", - "variant", // 15 - "macro", - "associatedtype", - "constant", - "associatedconstant", - "union", // 20 - "foreigntype", - "existential", - "attr", - "derive", - "traitalias", // 25 - "generic", - "attribute", -]; +const itemTypes = Object.freeze({ + keyword: 0, + primitive: 1, + mod: 2, + externcrate: 3, + import: 4, + struct: 5, + enum: 6, + fn: 7, + type: 8, + static: 9, + trait: 10, + impl: 11, + tymethod: 12, + method: 13, + structfield: 14, + variant: 15, + macro: 16, + associatedtype: 17, + constant: 18, + associatedconstant: 19, + union: 20, + foreigntype: 21, + existential: 22, + attr: 23, + derive: 24, + traitalias: 25, + generic: 26, + attribute: 27, +}); +const itemTypesName = Array.from(Object.keys(itemTypes)); + +// When filtering, some types might be included as well. For example, when you filter on `constant`, +// we also include associated constant items. +// +// This map is built as follows: the first item of the array is the type to be included when the +// second type of the array is used as filter. +const itemParents = new Map([ + [itemTypes.associatedconstant, itemTypes.constant], + [itemTypes.method, itemTypes.fn], + [itemTypes.tymethod, itemTypes.fn], + [itemTypes.primitive, itemTypes.type], + [itemTypes.associatedtype, itemTypes.type], + [itemTypes.traitalias, itemTypes.trait], + [itemTypes.attr, itemTypes.macro], + [itemTypes.derive, itemTypes.macro], + [itemTypes.externcrate, itemTypes.import], +]); -// used for special search precedence -/** @type {rustdoc.ItemType} */ -const TY_PRIMITIVE = 1; -/** @type {rustdoc.ItemType} */ -const TY_GENERIC = 26; -/** @type {rustdoc.ItemType} */ -const TY_IMPORT = 4; -/** @type {rustdoc.ItemType} */ -const TY_TRAIT = 10; -/** @type {rustdoc.ItemType} */ -const TY_FN = 7; -/** @type {rustdoc.ItemType} */ -const TY_METHOD = 13; -/** @type {rustdoc.ItemType} */ -const TY_TYMETHOD = 12; -/** @type {rustdoc.ItemType} */ -const TY_ASSOCTYPE = 17; const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../"; // Hard limit on how deep to recurse into generics when doing type-driven search. @@ -302,7 +303,7 @@ function isEndCharacter(c) { * @returns */ function isFnLikeTy(ty) { - return ty === TY_FN || ty === TY_METHOD || ty === TY_TYMETHOD; + return ty === itemTypes.fn || ty === itemTypes.method || ty === itemTypes.tymethod; } /** @@ -1205,8 +1206,9 @@ function itemTypeFromName(typename) { if (typename === null) { return NO_TYPE_FILTER; } - const index = itemTypes.findIndex(i => i === typename); - if (index < 0) { + // @ts-expect-error + const index = itemTypes[typename]; + if (index === undefined) { throw ["Unknown type filter ", typename]; } return index; @@ -1329,21 +1331,21 @@ class DocSearch { } return -1; }; - const typeNameIdOfOutput = await first(output, TY_ASSOCTYPE, ""); - const typeNameIdOfFnPtr = await first(fn, TY_PRIMITIVE, ""); - const typeNameIdOfFn = await first(fn, TY_TRAIT, "core::ops"); - const typeNameIdOfFnMut = await first(fnMut, TY_TRAIT, "core::ops"); - const typeNameIdOfFnOnce = await first(fnOnce, TY_TRAIT, "core::ops"); - const typeNameIdOfArray = await first(array, TY_PRIMITIVE, ""); - const typeNameIdOfSlice = await first(slice, TY_PRIMITIVE, ""); - const typeNameIdOfArrayOrSlice = await first(arrayOrSlice, TY_PRIMITIVE, ""); - const typeNameIdOfTuple = await first(tuple, TY_PRIMITIVE, ""); - const typeNameIdOfUnit = await first(unit, TY_PRIMITIVE, ""); - const typeNameIdOfTupleOrUnit = await first(tupleOrUnit, TY_PRIMITIVE, ""); - const typeNameIdOfReference = await first(reference, TY_PRIMITIVE, ""); - const typeNameIdOfPointer = await first(pointer, TY_PRIMITIVE, ""); - const typeNameIdOfHof = await first(hof, TY_PRIMITIVE, ""); - const typeNameIdOfNever = await first(never, TY_PRIMITIVE, ""); + const typeNameIdOfOutput = await first(output, itemTypes.associatedtype, ""); + const typeNameIdOfFnPtr = await first(fn, itemTypes.primitive, ""); + const typeNameIdOfFn = await first(fn, itemTypes.trait, "core::ops"); + const typeNameIdOfFnMut = await first(fnMut, itemTypes.trait, "core::ops"); + const typeNameIdOfFnOnce = await first(fnOnce, itemTypes.trait, "core::ops"); + const typeNameIdOfArray = await first(array, itemTypes.primitive, ""); + const typeNameIdOfSlice = await first(slice, itemTypes.primitive, ""); + const typeNameIdOfArrayOrSlice = await first(arrayOrSlice, itemTypes.primitive, ""); + const typeNameIdOfTuple = await first(tuple, itemTypes.primitive, ""); + const typeNameIdOfUnit = await first(unit, itemTypes.primitive, ""); + const typeNameIdOfTupleOrUnit = await first(tupleOrUnit, itemTypes.primitive, ""); + const typeNameIdOfReference = await first(reference, itemTypes.primitive, ""); + const typeNameIdOfPointer = await first(pointer, itemTypes.primitive, ""); + const typeNameIdOfHof = await first(hof, itemTypes.primitive, ""); + const typeNameIdOfNever = await first(never, itemTypes.primitive, ""); this.typeNameIds = { typeNameIdOfOutput, typeNameIdOfFnPtr, @@ -1520,7 +1522,7 @@ class DocSearch { /** @param {rustdoc.ParserQueryElement} elem */ const checkTypeFilter = elem => { const ty = itemTypeFromName(elem.typeFilter); - if (ty === TY_GENERIC && elem.generics.length !== 0) { + if (ty === itemTypes.generic && elem.generics.length !== 0) { throw [ "Generic type parameter ", elem.name, @@ -2033,7 +2035,7 @@ class DocSearch { result = { id, name: "", - ty: TY_GENERIC, + ty: itemTypes.generic, path: null, exactPath: null, generics, @@ -2045,7 +2047,7 @@ class DocSearch { result = { id: null, name: "", - ty: TY_GENERIC, + ty: itemTypes.generic, path: null, exactPath: null, generics, @@ -2062,7 +2064,7 @@ class DocSearch { return { id: null, name: "", - ty: TY_GENERIC, + ty: itemTypes.generic, path: null, exactPath: null, generics, @@ -2149,7 +2151,7 @@ class DocSearch { let displayPath; let href; let traitPath = null; - const type = itemTypes[item.ty]; + const type = itemTypesName[item.ty]; const name = item.name; let path = item.modulePath; let exactPath = item.exactModulePath; @@ -2173,7 +2175,7 @@ class DocSearch { } else if (item.parent) { const myparent = item.parent; let anchor = type + "." + name; - const parentType = itemTypes[myparent.path.ty]; + const parentType = itemTypesName[myparent.path.ty]; let pageType = parentType; let pageName = myparent.name; exactPath = `${myparent.path.exactModulePath}::${myparent.name}`; @@ -2520,11 +2522,11 @@ class DocSearch { whereClause.set(fnParamNames[-1 - fnType.id], where); } } else { - if (fnType.ty === TY_PRIMITIVE) { + if (fnType.ty === itemTypes.primitive) { if (await writeSpecialPrimitive(fnType, result)) { return; } - } else if (fnType.ty === TY_TRAIT && ( + } else if (fnType.ty === itemTypes.trait && ( fnType.id === typeNameIds.typeNameIdOfFn || fnType.id === typeNameIds.typeNameIdOfFnMut || fnType.id === typeNameIds.typeNameIdOfFnOnce || @@ -2691,8 +2693,8 @@ class DocSearch { // 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; + if (ty === itemTypes.tymethod) { + ty = itemTypes.method; } // To be sure than it some items aren't considered as duplicate. obj.fullPath = res[2] + "|" + ty; @@ -2714,10 +2716,10 @@ class DocSearch { // 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])) { + if (obj.item.ty === itemTypes.import && duplicates.has(res[2])) { continue; } - if (duplicates.has(res[2] + "|" + TY_IMPORT)) { + if (duplicates.has(res[2] + "|" + itemTypes.import)) { continue; } duplicates.add(obj.fullPath); @@ -3894,24 +3896,8 @@ class DocSearch { if (filter <= NO_TYPE_FILTER || filter === type) return true; // Match related items - const name = itemTypes[type]; - switch (itemTypes[filter]) { - case "constant": - return name === "associatedconstant"; - case "fn": - return name === "method" || name === "tymethod"; - case "type": - return name === "primitive" || name === "associatedtype"; - case "trait": - return name === "traitalias"; - case "macro": - return name === "attr" || name === "derive"; - case "import": - return name === "externcrate"; - } - - // No match - return false; + // @ts-expect-error + return filter === itemParents.get(type); } const innerRunNameQuery = @@ -4246,7 +4232,7 @@ class DocSearch { * ]>[]} * */ const typePromises = []; - if (typeFilter !== TY_GENERIC && searchResults) { + if (typeFilter !== itemTypes.generic && searchResults) { for (const id of searchResults.matches().entries()) { typePromises.push(Promise.all([ this.getName(id), @@ -4262,7 +4248,7 @@ class DocSearch { ty && !ty[polarity].every(bitmap => { return bitmap.isEmpty(); }) && - path && path.ty !== TY_ASSOCTYPE && + path && path.ty !== itemTypes.associatedtype && (elem.pathWithoutLast.length === 0 || checkPath( elem.pathWithoutLast, @@ -4270,14 +4256,14 @@ class DocSearch { ) === 0), ); if (types.length === 0) { - const areGenericsAllowed = typeFilter === TY_GENERIC || ( + const areGenericsAllowed = typeFilter === itemTypes.generic || ( typeFilter === -1 && (parsedQuery.totalElems > 1 || parsedQuery.hasReturnArrow) && elem.pathWithoutLast.length === 0 && elem.generics.length === 0 && elem.bindings.size === 0 ); - if (typeFilter !== TY_GENERIC && + if (typeFilter !== itemTypes.generic && (elem.name.length >= 3 || !areGenericsAllowed) ) { /** @type {string|null} */ @@ -4301,7 +4287,7 @@ class DocSearch { !ty[polarity].every(bitmap => { return bitmap.isEmpty(); }) && - path.ty !== TY_ASSOCTYPE + path.ty !== itemTypes.associatedtype ) { let dist = editDistance( name, @@ -4363,7 +4349,7 @@ class DocSearch { queryElem: { name: elem.name, id: (-genericId) - 1, - typeFilter: TY_GENERIC, + typeFilter: itemTypes.generic, generics: [], bindings: EMPTY_BINDINGS_MAP, fullPath: elem.fullPath, @@ -4930,7 +4916,7 @@ async function addTab(results, query, display, finishedCallback, isTypeSearch) { count += 1; const name = obj.item.name; - const type = itemTypes[obj.item.ty]; + const type = itemTypesName[obj.item.ty]; const longType = longItemTypes[obj.item.ty]; const typeName = longType.length !== 0 ? `${longType}` : "?";