Skip to content

Commit

Permalink
[file-search] match against relative paths (not absolute) #4537
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov committed Mar 13, 2019
1 parent fb4eb30 commit 9bb5937
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 9 deletions.
33 changes: 33 additions & 0 deletions packages/file-search/src/node/file-search-service-impl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
********************************************************************************/

import { expect } from 'chai';
import * as assert from 'assert';
import * as path from 'path';
import { FileSearchServiceImpl } from './file-search-service-impl';
import { FileUri } from '@theia/core/lib/node';
import { Container, ContainerModule } from 'inversify';
import { CancellationTokenSource } from '@theia/core';
import { bindLogger } from '@theia/core/lib/node/logger-backend-module';
import processBackendModule from '@theia/process/lib/node/process-backend-module';
import URI from '@theia/core/lib/common/uri';

// tslint:disable:no-unused-expression

Expand Down Expand Up @@ -118,4 +120,35 @@ describe('search-service', function () {
expect(matches.length).to.eq(0);
});
});

describe('irrelevant absolute results', () => {
const rootUri = FileUri.create(path.resolve(__dirname, '../../../../..'));

it('not fuzzy', async () => {
const matches = await service.find('theia', { rootUris: [rootUri.toString()], fuzzyMatch: false, useGitIgnore: true, limit: 200 });
for (const match of matches) {
const relativUri = rootUri.relative(new URI(match));
if (relativUri) {
const relativMatch = relativUri.toString();
assert.notEqual(relativMatch.indexOf('theia'), -1, relativMatch);
}
}
});

it('fuzzy', async () => {
const matches = await service.find('shell', { rootUris: [rootUri.toString()], fuzzyMatch: true, useGitIgnore: true, limit: 200 });
for (const match of matches) {
const relativUri = rootUri.relative(new URI(match));
if (relativUri) {
const relativMatch = relativUri.toString();
let position = 0;
for (const ch of 'shell') {
position = relativMatch.indexOf(ch, position);
assert.notEqual(position, -1, relativMatch);
}
}
}
});
});

});
28 changes: 19 additions & 9 deletions packages/file-search/src/node/file-search-service-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import * as readline from 'readline';
import * as fuzzy from 'fuzzy';
import { injectable, inject } from 'inversify';
import URI from '@theia/core/lib/common/uri';
import { FileSearchService } from '../common/file-search-service';
import { RawProcessFactory } from '@theia/process/lib/node';
import { rgPath } from 'vscode-ripgrep';
Expand Down Expand Up @@ -47,7 +48,7 @@ export class FileSearchServiceImpl implements FileSearchService {
try {
const results = await Promise.all([
this.doGlobSearch(searchPattern, args.slice(), opts.limit, cancellationToken),
this.doStringSearch(searchPattern, args.slice(), opts.limit, opts.fuzzyMatch, cancellationToken)
this.doStringSearch(searchPattern, args.slice(), opts, cancellationToken)
]);
const matches = Array.from(new Set([...results[0], ...results[1].exactMatches])).sort().slice(0, opts.limit);
if (matches.length === opts.limit) {
Expand Down Expand Up @@ -104,7 +105,7 @@ export class FileSearchServiceImpl implements FileSearchService {
}

private doStringSearch(
stringPattern: string, searchArgs: string[], limit: number, allowFuzzySearch: boolean, cancellationToken?: CancellationToken
stringPattern: string, searchArgs: string[], options: Required<Pick<FileSearchService.Options, 'limit' | 'fuzzyMatch' | 'rootUris'>>, cancellationToken?: CancellationToken
): Promise<{ exactMatches: string[], fuzzyMatches: string[] }> {
const resultDeferred = new Deferred<{ exactMatches: string[], fuzzyMatches: string[] }>();
const process = this.rawProcessFactory({
Expand All @@ -116,26 +117,35 @@ export class FileSearchServiceImpl implements FileSearchService {
process.kill();
resultDeferred.resolve({ exactMatches: [], fuzzyMatches: [] });
}, cancellationToken);
const rootUris = options.rootUris.map(uri => new URI(uri));
const lineReader = readline.createInterface({
input: process.output,
output: process.input
});
const exactMatches: string[] = [];
const fuzzyMatches: string[] = [];
lineReader.on('line', line => {
if (exactMatches.length >= limit) {
if (exactMatches.length >= options.limit) {
process.kill();
} else {
const fileUriStr = FileUri.create(line).toString();
if (line.toLocaleLowerCase().indexOf(stringPattern.toLocaleLowerCase()) !== -1) {
exactMatches.push(fileUriStr);
} else if (allowFuzzySearch && fuzzy.test(stringPattern, line)) {
fuzzyMatches.push(fileUriStr);
const fileUri = FileUri.create(line);
for (const rootUri of rootUris) {
const relativeUri = rootUri.relative(fileUri);
if (relativeUri) {
const relativeUriStr = relativeUri.toString();
if (relativeUriStr.toLocaleLowerCase().indexOf(stringPattern.toLocaleLowerCase()) !== -1) {
exactMatches.push(fileUri.toString());
return;
} else if (options.fuzzyMatch && fuzzy.test(stringPattern, relativeUriStr)) {
fuzzyMatches.push(fileUri.toString());
return;
}
}
}
}
});
process.output.on('close', () => {
const fuzzyResult = fuzzyMatches.slice(0, limit - exactMatches.length);
const fuzzyResult = fuzzyMatches.slice(0, options.limit - exactMatches.length);
resultDeferred.resolve({ exactMatches, fuzzyMatches: fuzzyResult });
});
process.onError(e => {
Expand Down

0 comments on commit 9bb5937

Please sign in to comment.