Skip to content

Commit 56c6946

Browse files
committed
Fix issue with searching using workspace folder name. Add file search integration tests
Fix microsoft#97352
1 parent 306235b commit 56c6946

5 files changed

Lines changed: 135 additions & 16 deletions

File tree

src/vs/workbench/services/search/common/search.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export function resultIsMatch(result: ITextSearchResult): result is ITextSearchM
183183
}
184184

185185
export interface IProgressMessage {
186-
message?: string;
186+
message: string;
187187
}
188188

189189
export type ISearchProgressItem = IFileMatch | IProgressMessage;
@@ -192,8 +192,8 @@ export function isFileMatch(p: ISearchProgressItem): p is IFileMatch {
192192
return !!(<IFileMatch>p).resource;
193193
}
194194

195-
export function isProgressMessage(p: ISearchProgressItem): p is IProgressMessage {
196-
return !isFileMatch(p);
195+
export function isProgressMessage(p: ISearchProgressItem | ISerializedSearchProgressItem): p is IProgressMessage {
196+
return !!(p as IProgressMessage).message;
197197
}
198198

199199
export interface ISearchCompleteStats {
@@ -468,7 +468,7 @@ export interface IRawFileMatch {
468468
*
469469
* If not given, the search algorithm should use `relativePath`.
470470
*/
471-
searchPath?: string;
471+
searchPath: string | undefined;
472472
}
473473

474474
export interface ISearchEngine<T> {

src/vs/workbench/services/search/node/fileSearch.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ import { IFileQuery, IFolderQuery, IProgressMessage, ISearchEngineStats, IRawFil
2424
import { spawnRipgrepCmd } from './ripgrepFileSearch';
2525
import { prepareQuery } from 'vs/base/common/fuzzyScorer';
2626

27-
interface IDirectoryEntry {
27+
interface IDirectoryEntry extends IRawFileMatch {
2828
base: string;
29-
relativePath: string;
3029
basename: string;
3130
}
3231

@@ -122,7 +121,7 @@ export class FileWalker {
122121
}
123122

124123
// File: Check for match on file pattern and include pattern
125-
this.matchFile(onResult, { relativePath: extraFilePath.fsPath /* no workspace relative path */ });
124+
this.matchFile(onResult, { relativePath: extraFilePath.fsPath /* no workspace relative path */, searchPath: undefined });
126125
});
127126

128127
this.cmdSW = StopWatch.create(false);
@@ -260,7 +259,7 @@ export class FileWalker {
260259
}
261260

262261
// TODO: Optimize siblings clauses with ripgrep here.
263-
this.addDirectoryEntries(tree, rootFolder, relativeFiles, onResult);
262+
this.addDirectoryEntries(folderQuery, tree, rootFolder, relativeFiles, onResult);
264263

265264
if (last) {
266265
this.matchDirectoryTree(tree, rootFolder, onResult);
@@ -389,13 +388,17 @@ export class FileWalker {
389388
return tree;
390389
}
391390

392-
private addDirectoryEntries({ pathToEntries }: IDirectoryTree, base: string, relativeFiles: string[], onResult: (result: IRawFileMatch) => void) {
391+
private addDirectoryEntries(folderQuery: IFolderQuery, { pathToEntries }: IDirectoryTree, base: string, relativeFiles: string[], onResult: (result: IRawFileMatch) => void) {
393392
// Support relative paths to files from a root resource (ignores excludes)
394393
if (relativeFiles.indexOf(this.filePattern) !== -1) {
395-
this.matchFile(onResult, { base: base, relativePath: this.filePattern });
394+
this.matchFile(onResult, {
395+
base,
396+
relativePath: this.filePattern,
397+
searchPath: this.getSearchPath(folderQuery, this.filePattern)
398+
});
396399
}
397400

398-
function add(relativePath: string) {
401+
const add = (relativePath: string) => {
399402
const basename = path.basename(relativePath);
400403
const dirname = path.dirname(relativePath);
401404
let entries = pathToEntries[dirname];
@@ -406,9 +409,10 @@ export class FileWalker {
406409
entries.push({
407410
base,
408411
relativePath,
409-
basename
412+
basename,
413+
searchPath: this.getSearchPath(folderQuery, relativePath),
410414
});
411-
}
415+
};
412416
relativeFiles.forEach(add);
413417
}
414418

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as assert from 'assert';
7+
import { getPathFromAmdModule } from 'vs/base/common/amd';
8+
import * as path from 'vs/base/common/path';
9+
import { URI } from 'vs/base/common/uri';
10+
import { IFileQuery, IFolderQuery, ISerializedSearchProgressItem, isProgressMessage, QueryType } from 'vs/workbench/services/search/common/search';
11+
import { SearchService } from 'vs/workbench/services/search/node/rawSearchService';
12+
13+
const TEST_FIXTURES = path.normalize(getPathFromAmdModule(require, './fixtures'));
14+
const TEST_FIXTURES2 = path.normalize(getPathFromAmdModule(require, './fixtures2'));
15+
const EXAMPLES_FIXTURES = path.join(TEST_FIXTURES, 'examples');
16+
const MORE_FIXTURES = path.join(TEST_FIXTURES, 'more');
17+
const TEST_ROOT_FOLDER: IFolderQuery = { folder: URI.file(TEST_FIXTURES) };
18+
const ROOT_FOLDER_QUERY: IFolderQuery[] = [
19+
TEST_ROOT_FOLDER
20+
];
21+
22+
const MULTIROOT_QUERIES: IFolderQuery[] = [
23+
{ folder: URI.file(EXAMPLES_FIXTURES), folderName: 'examples_folder' },
24+
{ folder: URI.file(MORE_FIXTURES) }
25+
];
26+
27+
async function doSearchTest(query: IFileQuery, expectedResultCount: number | Function): Promise<void> {
28+
const svc = new SearchService();
29+
30+
const results: ISerializedSearchProgressItem[] = [];
31+
await svc.doFileSearch(query, e => {
32+
if (!isProgressMessage(e)) {
33+
if (Array.isArray(e)) {
34+
results.push(...e);
35+
} else {
36+
results.push(e);
37+
}
38+
}
39+
});
40+
41+
assert.equal(results.length, expectedResultCount, `rg ${results.length} !== ${expectedResultCount}`);
42+
}
43+
44+
suite('FileSearch-integration', function () {
45+
this.timeout(1000 * 60); // increase timeout for this suite
46+
47+
test('File - simple', () => {
48+
const config: IFileQuery = {
49+
type: QueryType.File,
50+
folderQueries: ROOT_FOLDER_QUERY
51+
};
52+
53+
return doSearchTest(config, 14);
54+
});
55+
56+
test('File - filepattern', () => {
57+
const config: IFileQuery = {
58+
type: QueryType.File,
59+
folderQueries: ROOT_FOLDER_QUERY,
60+
filePattern: 'anotherfile'
61+
};
62+
63+
return doSearchTest(config, 1);
64+
});
65+
66+
test('File - exclude', () => {
67+
const config: IFileQuery = {
68+
type: QueryType.File,
69+
folderQueries: ROOT_FOLDER_QUERY,
70+
filePattern: 'file',
71+
excludePattern: { '**/anotherfolder/**': true }
72+
};
73+
74+
return doSearchTest(config, 2);
75+
});
76+
77+
test('File - multiroot', () => {
78+
const config: IFileQuery = {
79+
type: QueryType.File,
80+
folderQueries: MULTIROOT_QUERIES,
81+
filePattern: 'file',
82+
excludePattern: { '**/anotherfolder/**': true }
83+
};
84+
85+
return doSearchTest(config, 2);
86+
});
87+
88+
test('File - multiroot with folder name', () => {
89+
const config: IFileQuery = {
90+
type: QueryType.File,
91+
folderQueries: MULTIROOT_QUERIES,
92+
filePattern: 'examples_folder anotherfile'
93+
};
94+
95+
return doSearchTest(config, 1);
96+
});
97+
98+
test('File - multiroot with folder name and sibling exclude', () => {
99+
const config: IFileQuery = {
100+
type: QueryType.File,
101+
folderQueries: [
102+
{ folder: URI.file(TEST_FIXTURES), folderName: 'folder1' },
103+
{ folder: URI.file(TEST_FIXTURES2) }
104+
],
105+
filePattern: 'folder1 site',
106+
excludePattern: { '*.css': { when: '$(basename).less' } }
107+
};
108+
109+
return doSearchTest(config, 1);
110+
});
111+
});

src/vs/workbench/services/search/test/node/rawSearchService.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ suite('RawSearchService', () => {
8383
const rawMatch: IRawFileMatch = {
8484
base: path.normalize('/some'),
8585
relativePath: 'where',
86+
searchPath: undefined
8687
};
8788

8889
const match: ISerializedFileMatch = {
@@ -232,7 +233,8 @@ suite('RawSearchService', () => {
232233
base: path.normalize('/some/where'),
233234
relativePath,
234235
basename: relativePath,
235-
size: 3
236+
size: 3,
237+
searchPath: undefined
236238
}));
237239
const Engine = TestSearchEngine.bind(null, () => matches.shift()!);
238240
const service = new RawSearchService();
@@ -291,7 +293,8 @@ suite('RawSearchService', () => {
291293
base: path.normalize('/some/where'),
292294
relativePath,
293295
basename: relativePath,
294-
size: 3
296+
size: 3,
297+
searchPath: undefined
295298
}));
296299
const Engine = TestSearchEngine.bind(null, () => matches.shift()!);
297300
const service = new RawSearchService();
@@ -340,6 +343,7 @@ suite('RawSearchService', () => {
340343
matches.push({
341344
base: path.normalize('/some/where'),
342345
relativePath: 'bc',
346+
searchPath: undefined
343347
});
344348
const results: any[] = [];
345349
const cb: IProgressCallback = value => {

src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function doSearchTest(query: ITextQuery, expectedResultCount: number | Function)
4646
});
4747
}
4848

49-
suite('Search-integration', function () {
49+
suite('TextSearch-integration', function () {
5050
this.timeout(1000 * 60); // increase timeout for this suite
5151

5252
test('Text: GameOfLife', () => {

0 commit comments

Comments
 (0)