diff --git a/src/vs/workbench/api/common/shared/workspaceContains.ts b/src/vs/workbench/api/common/shared/workspaceContains.ts index 629c9994a87..74a283dce72 100644 --- a/src/vs/workbench/api/common/shared/workspaceContains.ts +++ b/src/vs/workbench/api/common/shared/workspaceContains.ts @@ -119,8 +119,7 @@ export function checkGlobFileExists( const queryBuilder = instantiationService.createInstance(QueryBuilder); const query = queryBuilder.file(folders.map(folder => toWorkspaceFolder(URI.revive(folder))), { _reason: 'checkExists', - includePattern: includes.join(', '), - expandPatterns: true, + includePattern: includes, exists: true }); diff --git a/src/vs/workbench/contrib/search/common/queryBuilder.ts b/src/vs/workbench/contrib/search/common/queryBuilder.ts index c7b9d17e10a..0025b2823b4 100644 --- a/src/vs/workbench/contrib/search/common/queryBuilder.ts +++ b/src/vs/workbench/contrib/search/common/queryBuilder.ts @@ -45,8 +45,8 @@ export interface ISearchPathsInfo { export interface ICommonQueryBuilderOptions { _reason?: string; - excludePattern?: string; - includePattern?: string; + excludePattern?: string | string[]; + includePattern?: string | string[]; extraFileResources?: uri[]; /** Parse the special ./ syntax supported by the searchview, and expand foo to ** /foo */ @@ -148,22 +148,20 @@ export class QueryBuilder { }; } - private commonQuery(folderResources: IWorkspaceFolderData[] = [], options: ICommonQueryBuilderOptions = {}): ICommonQueryProps { - let includeSearchPathsInfo: ISearchPathsInfo = {}; - if (options.includePattern) { - const includePattern = normalizeSlashes(options.includePattern); - includeSearchPathsInfo = options.expandPatterns ? - this.parseSearchPaths(includePattern) : - { pattern: patternListToIExpression(includePattern) }; + private handleIncludeExclude(pattern: string | string[] | undefined, expandPatterns: boolean | undefined): ISearchPathsInfo { + if (!pattern) { + return {}; } - let excludeSearchPathsInfo: ISearchPathsInfo = {}; - if (options.excludePattern) { - const excludePattern = normalizeSlashes(options.excludePattern); - excludeSearchPathsInfo = options.expandPatterns ? - this.parseSearchPaths(excludePattern) : - { pattern: patternListToIExpression(excludePattern) }; - } + pattern = Array.isArray(pattern) ? pattern.map(normalizeSlashes) : normalizeSlashes(pattern); + return expandPatterns ? + this.parseSearchPaths(pattern) : + { pattern: patternListToIExpression(...(Array.isArray(pattern) ? pattern : [pattern])) }; + } + + private commonQuery(folderResources: IWorkspaceFolderData[] = [], options: ICommonQueryBuilderOptions = {}): ICommonQueryProps { + const includeSearchPathsInfo: ISearchPathsInfo = this.handleIncludeExclude(options.includePattern, options.expandPatterns); + const excludeSearchPathsInfo: ISearchPathsInfo = this.handleIncludeExclude(options.excludePattern, options.expandPatterns); // Build folderQueries from searchPaths, if given, otherwise folderResources const includeFolderName = folderResources.length > 1; @@ -230,13 +228,14 @@ export class QueryBuilder { * * Public for test. */ - parseSearchPaths(pattern: string): ISearchPathsInfo { + parseSearchPaths(pattern: string | string[]): ISearchPathsInfo { const isSearchPath = (segment: string) => { // A segment is a search path if it is an absolute path or starts with ./, ../, .\, or ..\ return path.isAbsolute(segment) || /^\.\.?([\/\\]|$)/.test(segment); }; - const segments = splitGlobPattern(pattern) + const patterns = Array.isArray(pattern) ? pattern : splitGlobPattern(pattern); + const segments = patterns .map(segment => { const userHome = this.pathService.resolvedUserHome; if (userHome) { diff --git a/src/vs/workbench/contrib/search/test/browser/queryBuilder.test.ts b/src/vs/workbench/contrib/search/test/browser/queryBuilder.test.ts index 0271760eaf9..6aae8a9309b 100644 --- a/src/vs/workbench/contrib/search/test/browser/queryBuilder.test.ts +++ b/src/vs/workbench/contrib/search/test/browser/queryBuilder.test.ts @@ -93,7 +93,27 @@ suite('QueryBuilder', () => { }); }); - test('does not split glob pattern when expandPatterns disabled', () => { + test('splits include pattern when expandPatterns enabled', () => { + assertEqualQueries( + queryBuilder.file( + [ROOT_1_NAMED_FOLDER], + { includePattern: '**/foo, **/bar', expandPatterns: true }, + ), + { + folderQueries: [{ + folder: ROOT_1_URI + }], + type: QueryType.File, + includePattern: { + '**/foo': true, + '**/foo/**': true, + '**/bar': true, + '**/bar/**': true, + } + }); + }); + + test('does not split include pattern when expandPatterns disabled', () => { assertEqualQueries( queryBuilder.file( [ROOT_1_NAMED_FOLDER], @@ -110,6 +130,44 @@ suite('QueryBuilder', () => { }); }); + test('includePattern array', () => { + assertEqualQueries( + queryBuilder.file( + [ROOT_1_NAMED_FOLDER], + { includePattern: ['**/foo', '**/bar'] }, + ), + { + folderQueries: [{ + folder: ROOT_1_URI + }], + type: QueryType.File, + includePattern: { + '**/foo': true, + '**/bar': true + } + }); + }); + + test('includePattern array with expandPatterns', () => { + assertEqualQueries( + queryBuilder.file( + [ROOT_1_NAMED_FOLDER], + { includePattern: ['**/foo', '**/bar'], expandPatterns: true }, + ), + { + folderQueries: [{ + folder: ROOT_1_URI + }], + type: QueryType.File, + includePattern: { + '**/foo': true, + '**/foo/**': true, + '**/bar': true, + '**/bar/**': true, + } + }); + }); + test('folderResources', () => { assertEqualTextQueries( queryBuilder.text(