improve scorer on file paths

This commit is contained in:
Benjamin Pasero
2017-10-03 12:58:13 +02:00
parent 9c047a727e
commit ea0ef8e982
2 changed files with 63 additions and 10 deletions
+43 -8
View File
@@ -45,7 +45,7 @@ BEGIN THIRD PARTY
* Start of word/path bonus: 7
* Start of string bonus: 8
*/
export function _doScore(target: string, query: string): Score {
export function _doScore(target: string, query: string, inverse?: boolean): Score {
if (!target || !query) {
return NO_SCORE; // return early if target or query are undefined
}
@@ -62,11 +62,25 @@ export function _doScore(target: string, query: string): Score {
const matchingPositions: number[] = [];
let index = 0;
let startAt = 0;
let index: number;
let startAt: number;
if (!inverse) {
index = 0;
startAt = 0;
} else {
index = queryLen - 1; // inverse: from end of query to beginning
startAt = target.length - 1; // inverse: from end of target to beginning
}
let score = 0;
while (index < queryLen) {
let indexOf = targetLower.indexOf(queryLower[index], startAt);
while (inverse ? index >= 0 : index < queryLen) {
let indexOf: number;
if (!inverse) {
indexOf = targetLower.indexOf(queryLower[index], startAt);
} else {
indexOf = targetLower.lastIndexOf(queryLower[index], startAt); // inverse: look from the end
}
if (indexOf < 0) {
// console.log(`Character not part of target ${query[index]}`);
@@ -120,8 +134,18 @@ export function _doScore(target: string, query: string): Score {
// console.groupEnd();
startAt = indexOf + 1;
index++;
if (!inverse) {
startAt = indexOf + 1;
index++;
} else {
startAt = indexOf - 1; // inverse: go to begining from end
index--; // inverse: also for query index
}
}
// inverse: flip the matching positions so that they appear in order
if (inverse) {
matchingPositions.reverse();
}
const res: Score = (score > 0) ? [score, matchingPositions] : NO_SCORE;
@@ -248,7 +272,18 @@ function doScoreItem<T>(label: string, description: string, path: string, query:
const descriptionPrefixLength = descriptionPrefix.length;
const descriptionAndLabel = `${descriptionPrefix}${label}`;
const [labelDescriptionScore, labelDescriptionPositions] = _doScore(descriptionAndLabel, query);
let [labelDescriptionScore, labelDescriptionPositions] = _doScore(descriptionAndLabel, query);
// Optimize for file paths: score from the back to the beginning to catch more specific folder
// names that match on the end of the file. This yields better results in most cases.
if (!!path) {
const [labelDescriptionScoreInverse, labelDescriptionPositionsInverse] = _doScore(descriptionAndLabel, query, true /* inverse */);
if (labelDescriptionScoreInverse && labelDescriptionScoreInverse > labelDescriptionScore) {
labelDescriptionScore = labelDescriptionScoreInverse;
labelDescriptionPositions = labelDescriptionPositionsInverse;
}
}
if (labelDescriptionScore) {
const labelDescriptionMatches = createMatches(labelDescriptionPositions);
const labelMatch: IMatch[] = [];
+20 -2
View File
@@ -79,7 +79,7 @@ suite('Scorer', () => {
assert.equal(positions[1], 6);
});
test('scoreFile - matches are proper', function () {
test('scoreItem - matches are proper', function () {
let res = scorer.scoreItem(null, 'something', ResourceAccessor, cache);
assert.ok(!res.score);
@@ -151,7 +151,25 @@ suite('Scorer', () => {
assert.ok(pathRes.score > noRes.score);
});
test('compareFilesByScore - identity', function () {
test('scoreItem - optimize for file paths', function () {
const resource = URI.file('/xyz/others/spath/some/xsp/file123.txt');
// xsp is more relevant to the end of the file path even though it matches
// fuzzy also in the beginning. we verify the more relevant match at the
// end gets returned.
const pathRes = scorer.scoreItem(resource, 'xspfile123', ResourceAccessor, cache);
assert.ok(pathRes.score);
assert.ok(pathRes.descriptionMatch);
assert.ok(pathRes.labelMatch);
assert.equal(pathRes.labelMatch.length, 1);
assert.equal(pathRes.labelMatch[0].start, 0);
assert.equal(pathRes.labelMatch[0].end, 7);
assert.equal(pathRes.descriptionMatch.length, 1);
assert.equal(pathRes.descriptionMatch[0].start, 23);
assert.equal(pathRes.descriptionMatch[0].end, 26);
});
test('compareItemsByScore - identity', function () {
const resourceA = URI.file('/some/path/fileA.txt');
const resourceB = URI.file('/some/path/other/fileB.txt');
const resourceC = URI.file('/unrelated/some/path/other/fileC.txt');