From 5ed224d3616c41f82e81916ebb081cc921fc57da Mon Sep 17 00:00:00 2001 From: Folyd Date: Wed, 16 Oct 2024 01:04:11 +0800 Subject: [PATCH] Update latest search core --- core | 2 +- extension/search/docs/base.js | 6 +- extension/search/docs/{base-v2.js => core.js} | 109 ++++++++++-------- 3 files changed, 63 insertions(+), 54 deletions(-) rename extension/search/docs/{base-v2.js => core.js} (97%) diff --git a/core b/core index 94d784a..b08a81c 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 94d784a79113a1cca3b5ce4e83912894281ae137 +Subproject commit b08a81cc4fe4f24c88acb2f50185c1be6a98c6ee diff --git a/extension/search/docs/base.js b/extension/search/docs/base.js index 61fccc1..0764d16 100644 --- a/extension/search/docs/base.js +++ b/extension/search/docs/base.js @@ -1,6 +1,6 @@ -import DocSearchV2 from "./base-v2.js"; +import LibrustDocSearch from "./core.js"; -export default class DocSearch extends DocSearchV2 { +export default class DocSearch extends LibrustDocSearch { // The searchIndex should be Map([[crate, shards],) format constructor(name, searchIndex, rootPath, descShards) { super(searchIndex, rootPath, descShards); @@ -25,7 +25,7 @@ export default class DocSearch extends DocSearchV2 { async search(query) { if (!query) return []; - let result = await this.execQuery(DocSearchV2.parseQuery(query), null, this.name); + let result = await this.execQuery(LibrustDocSearch.parseQuery(query), null, this.name); return result.others || []; } } \ No newline at end of file diff --git a/extension/search/docs/base-v2.js b/extension/search/docs/core.js similarity index 97% rename from extension/search/docs/base-v2.js rename to extension/search/docs/core.js index 54137c8..203e1f2 100644 --- a/extension/search/docs/base-v2.js +++ b/extension/search/docs/core.js @@ -648,7 +648,7 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) { } const typeFilter = parserState.typeFilter; parserState.typeFilter = null; - if (name === "!") { + if (name.trim() === "!") { if (typeFilter !== null && typeFilter !== "primitive") { throw [ "Invalid search type: primitive never type ", @@ -916,10 +916,9 @@ class VlqHexDecoder { } // call after consuming `{` decodeList() { - const cb = "}".charCodeAt(0); let c = this.string.charCodeAt(this.offset); const ret = []; - while (c !== cb) { + while (c !== 125) { // 125 = "}" ret.push(this.decode()); c = this.string.charCodeAt(this.offset); } @@ -928,14 +927,13 @@ class VlqHexDecoder { } // consumes and returns a list or integer decode() { - const [ob, la] = ["{", "`"].map(c => c.charCodeAt(0)); let n = 0; let c = this.string.charCodeAt(this.offset); - if (c === ob) { + if (c === 123) { // 123 = "{" this.offset += 1; return this.decodeList(); } - while (c < la) { + while (c < 96) { // 96 = "`" n = (n << 4) | (c & 0xF); this.offset += 1; c = this.string.charCodeAt(this.offset); @@ -948,15 +946,14 @@ class VlqHexDecoder { } next() { const c = this.string.charCodeAt(this.offset); - const [zero, ua, la] = ["0", "@", "`"].map(c => c.charCodeAt(0)); // sixteen characters after "0" are backref - if (c >= zero && c < ua) { + if (c >= 48 && c < 64) { // 48 = "0", 64 = "@" this.offset += 1; - return this.backrefQueue[c - zero]; + return this.backrefQueue[c - 48]; } // special exception: 0 doesn't use backref encoding // it's already one character, and it's always nullish - if (c === la) { + if (c === 96) { // 96 = "`" this.offset += 1; return this.cons(0); } @@ -1087,7 +1084,7 @@ class RoaringBitmapBits { } -export default class DocSearchV2 { +export default class LibrustDocSearch { constructor(rawSearchIndex, rootPath, searchState) { /** * @type {Map} @@ -1510,7 +1507,6 @@ export default class DocSearchV2 { }; const searchIndex = []; - const charA = "A".charCodeAt(0); let currentIndex = 0; let id = 0; @@ -1586,8 +1582,10 @@ export default class DocSearchV2 { // An array of [(Number) item index, (Number) path index] // Used to de-duplicate inlined and re-exported stuff const itemReexports = new Map(crateCorpus.r); + // librustdoc changed crateCorpus.i from array to string, we need some compatible code. + const newCorpusFormat = typeof crateCorpus.i === "string"; // an array of (Number) the parent path index + 1 to `paths`, or 0 if none - const itemParentIdxs = crateCorpus.i; + const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop); // a map Number, string for impl disambiguators const implDisambiguator = new Map(crateCorpus.b); // an array of [(Number) item type, @@ -1634,6 +1632,8 @@ export default class DocSearchV2 { // faster analysis operations lastPath = ""; len = itemTypes.length; + let lastName = ""; + let lastWord = ""; for (let i = 0; i < len; ++i) { const bitIndex = i + 1; if (descIndex >= descShard.len && @@ -1649,10 +1649,8 @@ export default class DocSearchV2 { descIndex = 0; descShardList.push(descShard); } - let word = ""; - if (typeof itemNames[i] === "string") { - word = itemNames[i].toLowerCase(); - } + const name = itemNames[i] === "" ? lastName : itemNames[i]; + const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase(); const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; const type = itemFunctionDecoder.next(); if (type !== null) { @@ -1674,16 +1672,17 @@ export default class DocSearchV2 { } // This object should have exactly the same set of fields as the "crateRow" // object defined above. + const itemParentIdx = newCorpusFormat ? itemParentIdxDecoder.next(): crateCorpus.i[i]; const row = { crate, - ty: itemTypes.charCodeAt(i) - charA, - name: itemNames[i], + ty: itemTypes.charCodeAt(i) - 65, // 65 = "A" + name: newCorpusFormat? name : itemNames[i], path, descShard, descIndex, exactPath: itemReexports.has(i) ? itemPaths.get(itemReexports.get(i)) : path, - parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined, + parent: itemParentIdx > 0 ? paths[itemParentIdx - 1] : undefined, type, id, word, @@ -1698,6 +1697,8 @@ export default class DocSearchV2 { if (!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)) { descIndex += 1; } + lastName = name; + lastWord = word; } if (aliases) { @@ -1787,6 +1788,7 @@ export default class DocSearchV2 { // Total number of elements (includes generics). totalElems: 0, literalSearch: false, + hasReturnArrow: false, error: null, correction: null, proposeCorrectionFrom: null, @@ -1815,6 +1817,7 @@ export default class DocSearchV2 { continue; } else if (c === "-" || c === ">") { if (isReturnArrow(parserState)) { + query.hasReturnArrow = true; break; } throw ["Unexpected ", c, " (did you mean ", "->", "?)"]; @@ -1881,9 +1884,7 @@ export default class DocSearchV2 { // Get returned elements. getItemsBefore(query, parserState, query.returned, ""); // Nothing can come afterward! - if (query.returned.length === 0) { - throw ["Expected at least one item after ", "->"]; - } + query.hasReturnArrow = true; break; } else { parserState.pos += 1; @@ -2087,8 +2088,9 @@ export default class DocSearchV2 { * @param {string} preferredCrate * @returns {Promise<[ResultObject]>} */ - const sortResults = async (results, isType, preferredCrate) => { + const sortResults = async(results, isType, preferredCrate) => { const userQuery = parsedQuery.userQuery; + const casedUserQuery = parsedQuery.original; const result_list = []; for (const result of results.values()) { result.item = this.searchIndex[result.id]; @@ -2099,6 +2101,13 @@ export default class DocSearchV2 { result_list.sort((aaa, bbb) => { let a, b; + // sort by exact case-sensitive match + a = (aaa.item.name !== casedUserQuery); + b = (bbb.item.name !== casedUserQuery); + if (a !== b) { + return a - b; + } + // sort by exact match with regard to the last word (mismatch goes later) a = (aaa.word !== userQuery); b = (bbb.word !== userQuery); @@ -2822,7 +2831,7 @@ export default class DocSearchV2 { }; } - const handleAliases = async (ret, query, filterCrates, currentCrate) => { + const handleAliases = async(ret, query, filterCrates, currentCrate) => { const lowerQuery = query.toLowerCase(); // We separate aliases and crate aliases because we want to have current crate // aliases to be before the others in the displayed results. @@ -2964,30 +2973,30 @@ export default class DocSearchV2 { // fpDist is a minimum possible type distance, where "type distance" is the number of // atoms in the function not present in the query - const tfpDist = compareTypeFingerprints( - fullId, - parsedQuery.typeFingerprint, - ); - if (tfpDist !== null) { - const in_args = row.type && row.type.inputs - && checkIfInList(row.type.inputs, elem, row.type.where_clause, null, 0); - const returned = row.type && row.type.output - && checkIfInList(row.type.output, elem, row.type.where_clause, null, 0); - if (in_args) { - results_in_args.max_dist = Math.max(results_in_args.max_dist || 0, tfpDist); - const maxDist = results_in_args.size < MAX_RESULTS ? - (tfpDist + 1) : - results_in_args.max_dist; - addIntoResults(results_in_args, fullId, pos, -1, tfpDist, 0, maxDist); - } - if (returned) { - results_returned.max_dist = Math.max(results_returned.max_dist || 0, tfpDist); - const maxDist = results_returned.size < MAX_RESULTS ? - (tfpDist + 1) : - results_returned.max_dist; - addIntoResults(results_returned, fullId, pos, -1, tfpDist, 0, maxDist); - } - } + // const tfpDist = compareTypeFingerprints( + // fullId, + // parsedQuery.typeFingerprint, + // ); + // if (tfpDist !== null) { + // const in_args = row.type && row.type.inputs + // && checkIfInList(row.type.inputs, elem, row.type.where_clause, null, 0); + // const returned = row.type && row.type.output + // && checkIfInList(row.type.output, elem, row.type.where_clause, null, 0); + // if (in_args) { + // results_in_args.max_dist = Math.max(results_in_args.max_dist || 0, tfpDist); + // const maxDist = results_in_args.size < MAX_RESULTS ? + // (tfpDist + 1) : + // results_in_args.max_dist; + // addIntoResults(results_in_args, fullId, pos, -1, tfpDist, 0, maxDist); + // } + // if (returned) { + // results_returned.max_dist = Math.max(results_returned.max_dist || 0, tfpDist); + // const maxDist = results_returned.size < MAX_RESULTS ? + // (tfpDist + 1) : + // results_returned.max_dist; + // addIntoResults(results_returned, fullId, pos, -1, tfpDist, 0, maxDist); + // } + // } if (!typePassesFilter(elem.typeFilter, row.ty)) { return; @@ -3233,7 +3242,7 @@ export default class DocSearchV2 { this.buildFunctionTypeFingerprint(elem, parsedQuery.typeFingerprint, fps); } - if (parsedQuery.foundElems === 1 && parsedQuery.returned.length === 0) { + if (parsedQuery.foundElems === 1 && !parsedQuery.hasReturnArrow) { if (parsedQuery.elems.length === 1) { const elem = parsedQuery.elems[0]; const length = this.searchIndex.length;