mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
Merge branch 'master' of https://github.com/Microsoft/vscode
This commit is contained in:
@@ -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[] = [];
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -17,7 +17,7 @@ import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/serv
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import * as minimist from 'minimist';
|
||||
import * as path from 'path';
|
||||
import { QuickOpenHandler, IQuickOpenRegistry, Extensions } from 'vs/workbench/browser/quickopen';
|
||||
import { IQuickOpenRegistry, Extensions } from 'vs/workbench/browser/quickopen';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { SearchService } from 'vs/workbench/services/search/node/searchService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
@@ -58,7 +58,7 @@ suite('QuickOpen performance (integration)', () => {
|
||||
|
||||
test('Measure', () => {
|
||||
if (process.env['VSCODE_PID']) {
|
||||
return; // TODO@Christoph find out why test fails when run from within VS Code
|
||||
return void 0; // TODO@Christoph find out why test fails when run from within VS Code
|
||||
}
|
||||
|
||||
const n = 3;
|
||||
@@ -88,27 +88,25 @@ suite('QuickOpen performance (integration)', () => {
|
||||
assert.ok(descriptor);
|
||||
|
||||
function measure() {
|
||||
return instantiationService.createInstance(descriptor)
|
||||
.then((handler: QuickOpenHandler) => {
|
||||
handler.onOpen();
|
||||
return handler.getResults('a').then(result => {
|
||||
const uncachedEvent = popEvent();
|
||||
assert.strictEqual(uncachedEvent.data.symbols.fromCache, false, 'symbols.fromCache');
|
||||
assert.strictEqual(uncachedEvent.data.files.fromCache, true, 'files.fromCache');
|
||||
if (testWorkspaceArg) {
|
||||
assert.ok(!!uncachedEvent.data.files.joined, 'files.joined');
|
||||
}
|
||||
return uncachedEvent;
|
||||
}).then(uncachedEvent => {
|
||||
return handler.getResults('ab').then(result => {
|
||||
const cachedEvent = popEvent();
|
||||
assert.strictEqual(uncachedEvent.data.symbols.fromCache, false, 'symbols.fromCache');
|
||||
assert.ok(cachedEvent.data.files.fromCache, 'filesFromCache');
|
||||
handler.onClose(false);
|
||||
return [uncachedEvent, cachedEvent];
|
||||
});
|
||||
});
|
||||
const handler = descriptor.instantiate(instantiationService);
|
||||
handler.onOpen();
|
||||
return handler.getResults('a').then(result => {
|
||||
const uncachedEvent = popEvent();
|
||||
assert.strictEqual(uncachedEvent.data.symbols.fromCache, false, 'symbols.fromCache');
|
||||
assert.strictEqual(uncachedEvent.data.files.fromCache, true, 'files.fromCache');
|
||||
if (testWorkspaceArg) {
|
||||
assert.ok(!!uncachedEvent.data.files.joined, 'files.joined');
|
||||
}
|
||||
return uncachedEvent;
|
||||
}).then(uncachedEvent => {
|
||||
return handler.getResults('ab').then(result => {
|
||||
const cachedEvent = popEvent();
|
||||
assert.strictEqual(uncachedEvent.data.symbols.fromCache, false, 'symbols.fromCache');
|
||||
assert.ok(cachedEvent.data.files.fromCache, 'filesFromCache');
|
||||
handler.onClose(false);
|
||||
return [uncachedEvent, cachedEvent];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function popEvent() {
|
||||
|
||||
Reference in New Issue
Block a user