Fix issue with searching using workspace folder name. Add file search integration tests
Fix #97352
This commit is contained in:
parent
306235b1e6
commit
56c6946bf2
5 changed files with 135 additions and 16 deletions
|
@ -183,7 +183,7 @@ export function resultIsMatch(result: ITextSearchResult): result is ITextSearchM
|
|||
}
|
||||
|
||||
export interface IProgressMessage {
|
||||
message?: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export type ISearchProgressItem = IFileMatch | IProgressMessage;
|
||||
|
@ -192,8 +192,8 @@ export function isFileMatch(p: ISearchProgressItem): p is IFileMatch {
|
|||
return !!(<IFileMatch>p).resource;
|
||||
}
|
||||
|
||||
export function isProgressMessage(p: ISearchProgressItem): p is IProgressMessage {
|
||||
return !isFileMatch(p);
|
||||
export function isProgressMessage(p: ISearchProgressItem | ISerializedSearchProgressItem): p is IProgressMessage {
|
||||
return !!(p as IProgressMessage).message;
|
||||
}
|
||||
|
||||
export interface ISearchCompleteStats {
|
||||
|
@ -468,7 +468,7 @@ export interface IRawFileMatch {
|
|||
*
|
||||
* If not given, the search algorithm should use `relativePath`.
|
||||
*/
|
||||
searchPath?: string;
|
||||
searchPath: string | undefined;
|
||||
}
|
||||
|
||||
export interface ISearchEngine<T> {
|
||||
|
|
|
@ -24,9 +24,8 @@ import { IFileQuery, IFolderQuery, IProgressMessage, ISearchEngineStats, IRawFil
|
|||
import { spawnRipgrepCmd } from './ripgrepFileSearch';
|
||||
import { prepareQuery } from 'vs/base/common/fuzzyScorer';
|
||||
|
||||
interface IDirectoryEntry {
|
||||
interface IDirectoryEntry extends IRawFileMatch {
|
||||
base: string;
|
||||
relativePath: string;
|
||||
basename: string;
|
||||
}
|
||||
|
||||
|
@ -122,7 +121,7 @@ export class FileWalker {
|
|||
}
|
||||
|
||||
// File: Check for match on file pattern and include pattern
|
||||
this.matchFile(onResult, { relativePath: extraFilePath.fsPath /* no workspace relative path */ });
|
||||
this.matchFile(onResult, { relativePath: extraFilePath.fsPath /* no workspace relative path */, searchPath: undefined });
|
||||
});
|
||||
|
||||
this.cmdSW = StopWatch.create(false);
|
||||
|
@ -260,7 +259,7 @@ export class FileWalker {
|
|||
}
|
||||
|
||||
// TODO: Optimize siblings clauses with ripgrep here.
|
||||
this.addDirectoryEntries(tree, rootFolder, relativeFiles, onResult);
|
||||
this.addDirectoryEntries(folderQuery, tree, rootFolder, relativeFiles, onResult);
|
||||
|
||||
if (last) {
|
||||
this.matchDirectoryTree(tree, rootFolder, onResult);
|
||||
|
@ -389,13 +388,17 @@ export class FileWalker {
|
|||
return tree;
|
||||
}
|
||||
|
||||
private addDirectoryEntries({ pathToEntries }: IDirectoryTree, base: string, relativeFiles: string[], onResult: (result: IRawFileMatch) => void) {
|
||||
private addDirectoryEntries(folderQuery: IFolderQuery, { pathToEntries }: IDirectoryTree, base: string, relativeFiles: string[], onResult: (result: IRawFileMatch) => void) {
|
||||
// Support relative paths to files from a root resource (ignores excludes)
|
||||
if (relativeFiles.indexOf(this.filePattern) !== -1) {
|
||||
this.matchFile(onResult, { base: base, relativePath: this.filePattern });
|
||||
this.matchFile(onResult, {
|
||||
base,
|
||||
relativePath: this.filePattern,
|
||||
searchPath: this.getSearchPath(folderQuery, this.filePattern)
|
||||
});
|
||||
}
|
||||
|
||||
function add(relativePath: string) {
|
||||
const add = (relativePath: string) => {
|
||||
const basename = path.basename(relativePath);
|
||||
const dirname = path.dirname(relativePath);
|
||||
let entries = pathToEntries[dirname];
|
||||
|
@ -406,9 +409,10 @@ export class FileWalker {
|
|||
entries.push({
|
||||
base,
|
||||
relativePath,
|
||||
basename
|
||||
basename,
|
||||
searchPath: this.getSearchPath(folderQuery, relativePath),
|
||||
});
|
||||
}
|
||||
};
|
||||
relativeFiles.forEach(add);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileQuery, IFolderQuery, ISerializedSearchProgressItem, isProgressMessage, QueryType } from 'vs/workbench/services/search/common/search';
|
||||
import { SearchService } from 'vs/workbench/services/search/node/rawSearchService';
|
||||
|
||||
const TEST_FIXTURES = path.normalize(getPathFromAmdModule(require, './fixtures'));
|
||||
const TEST_FIXTURES2 = path.normalize(getPathFromAmdModule(require, './fixtures2'));
|
||||
const EXAMPLES_FIXTURES = path.join(TEST_FIXTURES, 'examples');
|
||||
const MORE_FIXTURES = path.join(TEST_FIXTURES, 'more');
|
||||
const TEST_ROOT_FOLDER: IFolderQuery = { folder: URI.file(TEST_FIXTURES) };
|
||||
const ROOT_FOLDER_QUERY: IFolderQuery[] = [
|
||||
TEST_ROOT_FOLDER
|
||||
];
|
||||
|
||||
const MULTIROOT_QUERIES: IFolderQuery[] = [
|
||||
{ folder: URI.file(EXAMPLES_FIXTURES), folderName: 'examples_folder' },
|
||||
{ folder: URI.file(MORE_FIXTURES) }
|
||||
];
|
||||
|
||||
async function doSearchTest(query: IFileQuery, expectedResultCount: number | Function): Promise<void> {
|
||||
const svc = new SearchService();
|
||||
|
||||
const results: ISerializedSearchProgressItem[] = [];
|
||||
await svc.doFileSearch(query, e => {
|
||||
if (!isProgressMessage(e)) {
|
||||
if (Array.isArray(e)) {
|
||||
results.push(...e);
|
||||
} else {
|
||||
results.push(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(results.length, expectedResultCount, `rg ${results.length} !== ${expectedResultCount}`);
|
||||
}
|
||||
|
||||
suite('FileSearch-integration', function () {
|
||||
this.timeout(1000 * 60); // increase timeout for this suite
|
||||
|
||||
test('File - simple', () => {
|
||||
const config: IFileQuery = {
|
||||
type: QueryType.File,
|
||||
folderQueries: ROOT_FOLDER_QUERY
|
||||
};
|
||||
|
||||
return doSearchTest(config, 14);
|
||||
});
|
||||
|
||||
test('File - filepattern', () => {
|
||||
const config: IFileQuery = {
|
||||
type: QueryType.File,
|
||||
folderQueries: ROOT_FOLDER_QUERY,
|
||||
filePattern: 'anotherfile'
|
||||
};
|
||||
|
||||
return doSearchTest(config, 1);
|
||||
});
|
||||
|
||||
test('File - exclude', () => {
|
||||
const config: IFileQuery = {
|
||||
type: QueryType.File,
|
||||
folderQueries: ROOT_FOLDER_QUERY,
|
||||
filePattern: 'file',
|
||||
excludePattern: { '**/anotherfolder/**': true }
|
||||
};
|
||||
|
||||
return doSearchTest(config, 2);
|
||||
});
|
||||
|
||||
test('File - multiroot', () => {
|
||||
const config: IFileQuery = {
|
||||
type: QueryType.File,
|
||||
folderQueries: MULTIROOT_QUERIES,
|
||||
filePattern: 'file',
|
||||
excludePattern: { '**/anotherfolder/**': true }
|
||||
};
|
||||
|
||||
return doSearchTest(config, 2);
|
||||
});
|
||||
|
||||
test('File - multiroot with folder name', () => {
|
||||
const config: IFileQuery = {
|
||||
type: QueryType.File,
|
||||
folderQueries: MULTIROOT_QUERIES,
|
||||
filePattern: 'examples_folder anotherfile'
|
||||
};
|
||||
|
||||
return doSearchTest(config, 1);
|
||||
});
|
||||
|
||||
test('File - multiroot with folder name and sibling exclude', () => {
|
||||
const config: IFileQuery = {
|
||||
type: QueryType.File,
|
||||
folderQueries: [
|
||||
{ folder: URI.file(TEST_FIXTURES), folderName: 'folder1' },
|
||||
{ folder: URI.file(TEST_FIXTURES2) }
|
||||
],
|
||||
filePattern: 'folder1 site',
|
||||
excludePattern: { '*.css': { when: '$(basename).less' } }
|
||||
};
|
||||
|
||||
return doSearchTest(config, 1);
|
||||
});
|
||||
});
|
|
@ -83,6 +83,7 @@ suite('RawSearchService', () => {
|
|||
const rawMatch: IRawFileMatch = {
|
||||
base: path.normalize('/some'),
|
||||
relativePath: 'where',
|
||||
searchPath: undefined
|
||||
};
|
||||
|
||||
const match: ISerializedFileMatch = {
|
||||
|
@ -232,7 +233,8 @@ suite('RawSearchService', () => {
|
|||
base: path.normalize('/some/where'),
|
||||
relativePath,
|
||||
basename: relativePath,
|
||||
size: 3
|
||||
size: 3,
|
||||
searchPath: undefined
|
||||
}));
|
||||
const Engine = TestSearchEngine.bind(null, () => matches.shift()!);
|
||||
const service = new RawSearchService();
|
||||
|
@ -291,7 +293,8 @@ suite('RawSearchService', () => {
|
|||
base: path.normalize('/some/where'),
|
||||
relativePath,
|
||||
basename: relativePath,
|
||||
size: 3
|
||||
size: 3,
|
||||
searchPath: undefined
|
||||
}));
|
||||
const Engine = TestSearchEngine.bind(null, () => matches.shift()!);
|
||||
const service = new RawSearchService();
|
||||
|
@ -340,6 +343,7 @@ suite('RawSearchService', () => {
|
|||
matches.push({
|
||||
base: path.normalize('/some/where'),
|
||||
relativePath: 'bc',
|
||||
searchPath: undefined
|
||||
});
|
||||
const results: any[] = [];
|
||||
const cb: IProgressCallback = value => {
|
||||
|
|
|
@ -46,7 +46,7 @@ function doSearchTest(query: ITextQuery, expectedResultCount: number | Function)
|
|||
});
|
||||
}
|
||||
|
||||
suite('Search-integration', function () {
|
||||
suite('TextSearch-integration', function () {
|
||||
this.timeout(1000 * 60); // increase timeout for this suite
|
||||
|
||||
test('Text: GameOfLife', () => {
|
||||
|
|
Loading…
Reference in a new issue