queryBuilder.ts ×27

Frontier kind: Code frontier

unlabeled · c_b08ff1283e85

36 tests · 27314 LOC · 134 files · introduces 0 tests · 187 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
27 ranges187 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
2729 ranges27314 lines · 134 files · Browse complete extent
All tests (intent)
36 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 187 introduced LOC across 27 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/services/search/common/queryBuilder.ts 187 introduced LOC · 27 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- queryBuilder.ts
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 arrays from '../../../../base/common/arrays.js';
7 > import * as collections from '../../../../base/common/collections.js';
8 > import * as glob from '../../../../base/common/glob.js';
9 > import { untildify } from '../../../../base/common/labels.js';
10 > import { ResourceMap } from '../../../../base/common/map.js';
11 > import { Schemas } from '../../../../base/common/network.js';
12 > import * as path from '../../../../base/common/path.js';
13 > import { isEqual, basename, relativePath, isAbsolutePath } from '../../../../base/common/resources.js';
14 > import * as strings from '../../../../base/common/strings.js';
15 > import { assertReturnsDefined, isDefined } from '../../../../base/common/types.js';
16 > import { URI, URI as uri, UriComponents } from '../../../../base/common/uri.js';
17 > import { isMultilineRegexSource } from '../../../../editor/common/model/textModelSearch.js';
18 > import * as nls from '../../../../nls.js';
19 > import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
20 > import { ILogService } from '../../../../platform/log/common/log.js';
21 > import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';
22 > import { IWorkspaceContextService, IWorkspaceFolderData, toWorkspaceFolder, WorkbenchState } from '../../../../platform/workspace/common/workspace.js';
23 > import { IEditorGroupsService } from '../../editor/common/editorGroupsService.js';
24 > import { IPathService } from '../../path/common/pathService.js';
25 > import { ExcludeGlobPattern, getExcludes, IAITextQuery, ICommonQueryProps, IFileQuery, IFolderQuery, IPatternInfo, ISearchConfiguration, ITextQuery, ITextSearchPreviewOptions, pathIncludedInQuery, QueryType } from './search.js';
26 > import { GlobPattern } from './searchExtTypes.js';
27 >
28 > /**
29 > * One folder to search and a glob expression that should be applied.
30 > */
31 > interface IOneSearchPathPattern {
32 > searchPath: uri;
33 > pattern?: string;
34 > }
35 >
36 > /**
37 > * One folder to search and a set of glob expressions that should be applied.
38 > */
39 > export interface ISearchPathPattern {
40 > searchPath: uri;
41 > pattern?: glob.IExpression;
42 > }
43 >
44 > type ISearchPathPatternBuilder = string | string[];
45 >
46 > export interface ISearchPatternBuilder<U extends UriComponents> {
47 > uri?: U;
48 > pattern: ISearchPathPatternBuilder;
49 > }
50 >
51 > export function isISearchPatternBuilder<U extends UriComponents>(object: ISearchPatternBuilder<U> | ISearchPathPatternBuilder): object is ISearchPatternBuilder<U> {
52 return (typeof object === 'object' && 'uri' in object && 'pattern' in object);
53 }
55 > export function globPatternToISearchPatternBuilder(globPattern: GlobPattern): ISearchPatternBuilder<URI> {
56
57 if (typeof globPattern === 'string') {
66 };
67 }
69 > /**
70 > * A set of search paths and a set of glob expressions that should be applied.
71 > */
72 > export interface ISearchPathsInfo {
73 > searchPaths?: ISearchPathPattern[];
74 > pattern?: glob.IExpression;
75 > }
76 >
77 > interface ICommonQueryBuilderOptions<U extends UriComponents = URI> {
78 > _reason?: string;
79 > excludePattern?: ISearchPatternBuilder<U>[];
80 > includePattern?: ISearchPathPatternBuilder;
81 > extraFileResources?: U[];
82 >
83 > /** Parse the special ./ syntax supported by the searchview, and expand foo to ** /foo */
84 > expandPatterns?: boolean;
85 >
86 > maxResults?: number;
87 > maxFileSize?: number;
88 > disregardIgnoreFiles?: boolean;
89 > disregardGlobalIgnoreFiles?: boolean;
90 > disregardParentIgnoreFiles?: boolean;
91 > disregardExcludeSettings?: boolean;
92 > disregardSearchExcludeSettings?: boolean;
93 > ignoreSymlinks?: boolean;
94 > ignoreGlobCase?: boolean;
95 > onlyOpenEditors?: boolean;
96 > changedFileUris?: URI[];
97 > onlyFileScheme?: boolean;
98 > }
99 >
100 > export interface IFileQueryBuilderOptions<U extends UriComponents = URI> extends ICommonQueryBuilderOptions<U> {
101 > filePattern?: string;
102 > exists?: boolean;
103 > sortByScore?: boolean;
104 > cacheKey?: string;
105 > shouldGlobSearch?: boolean;
106 > }
107 >
108 > export interface ITextQueryBuilderOptions<U extends UriComponents = URI> extends ICommonQueryBuilderOptions<U> {
109 > previewOptions?: ITextSearchPreviewOptions;
110 > fileEncoding?: string;
111 > surroundingContext?: number;
112 > isSmartCase?: boolean;
113 > notebookSearchConfig?: {
114 > includeMarkupInput: boolean;
115 > includeMarkupPreview: boolean;
116 > includeCodeInput: boolean;
117 > includeOutput: boolean;
118 > };
119 > }
120 >
121 > export class QueryBuilder {
122 >
123 > constructor(
124 @IConfigurationService private readonly configurationService: IConfigurationService,
125 @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
130 ) {
131 }
133 > aiText(contentPattern: string, folderResources?: uri[], options: ITextQueryBuilderOptions = {}): IAITextQuery {
134 const commonQuery = this.commonQuery(folderResources?.map(toWorkspaceFolder), options);
135 return {
139 };
140 }
142 > text(contentPattern: IPatternInfo, folderResources?: uri[], options: ITextQueryBuilderOptions = {}): ITextQuery {
143 contentPattern = this.getContentPattern(contentPattern, options);
144
155 };
156 }
158 > /**
159 > * Adjusts input pattern for config
160 > */
161 > private getContentPattern(inputPattern: IPatternInfo, options: ITextQueryBuilderOptions): IPatternInfo {
162 const searchConfig = this.configurationService.getValue<ISearchConfiguration>();
163
209 return newPattern;
210 }
212 > file(folders: (IWorkspaceFolderData | URI)[], options: IFileQueryBuilderOptions = {}): IFileQuery {
213 const commonQuery = this.commonQuery(folders, options);
214 return {
224 };
225 }
227 > private handleIncludeExclude(pattern: string | string[] | undefined, expandPatterns: boolean | undefined): ISearchPathsInfo {
228 if (!pattern) {
229 return {};
242 : { pattern: patternListToIExpression(...(Array.isArray(pattern) ? pattern : [pattern])) };
243 }
245 > private commonQuery(folderResources: (IWorkspaceFolderData | URI)[] = [], options: ICommonQueryBuilderOptions = {}): ICommonQueryProps<uri> {
246
247 let excludePatterns: string | string[] | undefined = Array.isArray(options.excludePattern) ? options.excludePattern.map(p => p.pattern).flat() : options.excludePattern;
293 return queryProps;
294 }
296 > private commonQueryFromFileList(files: URI[]): ICommonQueryProps<URI> {
297 const folderQueries: IFolderQuery[] = [];
298 const foldersToSearch: ResourceMap<IFolderQuery> = new ResourceMap();
333 };
334 }
336 > /**
337 > * Resolve isCaseSensitive flag based on the query and the isSmartCase flag, for search providers that don't support smart case natively.
338 > */
339 > private isCaseSensitive(contentPattern: IPatternInfo, options: ITextQueryBuilderOptions): boolean {
340 if (options.isSmartCase) {
341 if (contentPattern.isRegExp) {
351 return !!contentPattern.isCaseSensitive;
352 }
354 > private isMultiline(contentPattern: IPatternInfo): boolean {
355 if (contentPattern.isMultiline) {
356 return true;
367 return !!contentPattern.isMultiline;
368 }
370 > /**
371 > * Take the includePattern as seen in the search viewlet, and split into components that look like searchPaths, and
372 > * glob patterns. Glob patterns are expanded from 'foo/bar' to '{foo/bar/**, **\/foo/bar}.
373 > *
374 > * Public for test.
375 > */
376 > parseSearchPaths(pattern: string | string[]): ISearchPathsInfo {
377 const isSearchPath = (segment: string) => {
378 // A segment is a search path if it is an absolute path or starts with ./, ../, .\, or ..\
418 return result;
419 }
421 > private getExcludesForFolder(folderConfig: ISearchConfiguration, options: ICommonQueryBuilderOptions): glob.IExpression | undefined {
422 return options.disregardExcludeSettings ?
423 undefined :
424 getExcludes(folderConfig, !options.disregardSearchExcludeSettings);
425 }
427 > /**
428 > * Split search paths (./ or ../ or absolute paths in the includePatterns) into absolute paths and globs applied to those paths
429 > */
430 > private expandSearchPathPatterns(searchPaths: string[]): ISearchPathPattern[] {
431 if (!searchPaths || !searchPaths.length) {
432 // No workspace => ignore search paths
468 return Array.from(searchPathPatternMap.values());
469 }
471 > /**
472 > * Takes a searchPath like `./a/foo` or `../a/foo` and expands it to absolute paths for all the workspaces it matches.
473 > */
474 > private expandOneSearchPath(searchPath: string): IOneSearchPathPattern[] {
475 if (path.isAbsolute(searchPath)) {
476 const workspaceFolders = this.workspaceContextService.getWorkspace().folders;
535 }
536 }
538 > private resolveOneSearchPathPattern(oneExpandedResult: IOneSearchPathPattern, globPortion?: string): IOneSearchPathPattern[] {
539 const pattern = oneExpandedResult.pattern && globPortion ?
540 `${oneExpandedResult.pattern}/${globPortion}` :
556 return results;
557 }
559 > private getFolderQueryForSearchPath(searchPath: ISearchPathPattern, options: ICommonQueryBuilderOptions, searchPathExcludes: ISearchPathsInfo): IFolderQuery | null {
560 const rootConfig = this.getFolderQueryForRoot(toWorkspaceFolder(searchPath.searchPath), options, searchPathExcludes, false);
561 if (!rootConfig) {
570 };
571 }
573 > private getFolderQueryForRoot(folder: (IWorkspaceFolderData | URI), options: ICommonQueryBuilderOptions, searchPathExcludes: ISearchPathsInfo, includeFolderName: boolean): IFolderQuery | null {
574 let thisFolderExcludeSearchPathPattern: glob.IExpression | undefined;
575 const folderUri = URI.isUri(folder) ? folder : folder.uri;
624 };
625 }
626 > } queryBuilder.ts
627 >
628 function splitGlobFromPath(searchPath: string): { pathPortion: string; globPortion?: string } {
629 const globCharMatch = searchPath.match(/[\*\{\}\(\)\[\]\?]/);
650 };
651 }
653 function patternListToIExpression(...patterns: string[]): glob.IExpression | undefined {
654 return patterns.length ?
656 undefined;
657 }
659 function splitGlobPattern(pattern: string): string[] {
660 return glob.splitGlobAware(pattern, ',')
662 .filter(s => !!s.length);
663 }
665 > /**
666 > * Note - we used {} here previously but ripgrep can't handle nested {} patterns. See https://github.com/microsoft/vscode/issues/32761
667 > */
668 function expandGlobalGlob(pattern: string): string[] {
669 const patterns = [
674 return patterns.map(p => p.replace(/\*\*\/\*\*/g, '**'));
675 }
677 function normalizeSlashes(pattern: string): string {
678 return pattern.replace(/\\/g, '/');
679 }
681 > /**
682 > * Normalize slashes, remove `./` and trailing slashes
683 > */
684 function normalizeGlobPattern(pattern: string): string {
685 return normalizeSlashes(pattern)
687 .replace(/\/+$/g, '');
688 }
690 > /**
691 > * Escapes a path for use as a glob pattern that would match the input precisely.
692 > * Characters '?', '*', '[', and ']' are escaped into character range glob syntax
693 > * (for example, '?' becomes '[?]').
694 > * NOTE: This implementation makes no special cases for UNC paths. For example,
695 > * given the input "//?/C:/A?.txt", this would produce output '//[?]/C:/A[?].txt',
696 > * which may not be desirable in some cases. Use with caution if UNC paths could be expected.
697 > */
698 > export function escapeGlobPattern(path: string): string {
699 return path.replace(/([?*[\]])/g, '[$1]');
700 }
702 > /**
703 > * Construct an include pattern from a list of folders uris to search in.
704 > */
705 > export function resolveResourcesForSearchIncludes(resources: URI[], contextService: IWorkspaceContextService): string[] {
706 resources = arrays.distinct(resources, resource => resource.toString());
707