@codingame/monaco-vscode-search-service-override 3.2.3 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/search.js +4 -4
- package/external/rollup-plugin-styles/dist/runtime/inject-css.js +0 -3
- package/external/tslib/tslib.es6.js +0 -11
- package/override/vs/platform/dialogs/common/dialogs.js +0 -8
- package/vscode/src/vs/workbench/contrib/search/browser/anythingQuickAccess.js +0 -776
- package/vscode/src/vs/workbench/contrib/search/browser/media/anythingQuickAccess.css.js +0 -6
- package/vscode/src/vs/workbench/contrib/search/browser/media/searchview.css.js +0 -6
- package/vscode/src/vs/workbench/contrib/search/browser/patternInputWidget.js +0 -231
- package/vscode/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.js +0 -342
- package/vscode/src/vs/workbench/contrib/search/browser/replaceContributions.js +0 -8
- package/vscode/src/vs/workbench/contrib/search/browser/replaceService.js +0 -232
- package/vscode/src/vs/workbench/contrib/search/browser/search.contribution.js +0 -621
- package/vscode/src/vs/workbench/contrib/search/browser/searchActionsCopy.js +0 -209
- package/vscode/src/vs/workbench/contrib/search/browser/searchActionsNav.js +0 -511
- package/vscode/src/vs/workbench/contrib/search/browser/searchActionsRemoveReplace.js +0 -374
- package/vscode/src/vs/workbench/contrib/search/browser/searchActionsSymbol.js +0 -43
- package/vscode/src/vs/workbench/contrib/search/browser/searchActionsTextQuickAccess.js +0 -44
- package/vscode/src/vs/workbench/contrib/search/browser/searchActionsTopBar.js +0 -323
- package/vscode/src/vs/workbench/contrib/search/browser/searchFindInput.js +0 -47
- package/vscode/src/vs/workbench/contrib/search/browser/searchIcons.js +0 -96
- package/vscode/src/vs/workbench/contrib/search/browser/searchMessage.js +0 -66
- package/vscode/src/vs/workbench/contrib/search/browser/searchResultsView.js +0 -434
- package/vscode/src/vs/workbench/contrib/search/browser/searchView.js +0 -2096
- package/vscode/src/vs/workbench/contrib/search/browser/searchWidget.js +0 -667
- package/vscode/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.js +0 -234
- package/vscode/src/vs/workbench/contrib/search/common/cacheState.js +0 -87
- package/vscode/src/vs/workbench/contrib/searchEditor/browser/media/searchEditor.css.js +0 -6
- package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.js +0 -586
- package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditor.js +0 -736
- package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.js +0 -189
- package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.js +0 -320
- package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditorModel.js +0 -138
- package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.js +0 -293
- package/vscode/src/vs/workbench/services/search/common/searchService.js +0 -372
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import { coalesce, flatten } from 'vscode/vscode/vs/base/common/arrays';
|
|
2
|
-
import './media/searchEditor.css.js';
|
|
3
|
-
import { Range } from 'vscode/vscode/vs/editor/common/core/range';
|
|
4
|
-
import { localizeWithPath } from 'vscode/vscode/vs/nls';
|
|
5
|
-
import { searchMatchComparer } from 'vscode/vscode/vs/workbench/contrib/search/browser/searchModel';
|
|
6
|
-
import { ITextFileService } from 'vscode/vscode/vs/workbench/services/textfile/common/textfiles';
|
|
7
|
-
|
|
8
|
-
const lineDelimiter = '\n';
|
|
9
|
-
const translateRangeLines = (n) => (range) => ( new Range(
|
|
10
|
-
range.startLineNumber + n,
|
|
11
|
-
range.startColumn,
|
|
12
|
-
range.endLineNumber + n,
|
|
13
|
-
range.endColumn
|
|
14
|
-
));
|
|
15
|
-
const matchToSearchResultFormat = (match, longestLineNumber) => {
|
|
16
|
-
const getLinePrefix = (i) => `${match.range().startLineNumber + i}`;
|
|
17
|
-
const fullMatchLines = match.fullPreviewLines();
|
|
18
|
-
const results = [];
|
|
19
|
-
fullMatchLines
|
|
20
|
-
.forEach((sourceLine, i) => {
|
|
21
|
-
const lineNumber = getLinePrefix(i);
|
|
22
|
-
const paddingStr = ' '.repeat(longestLineNumber - lineNumber.length);
|
|
23
|
-
const prefix = ` ${paddingStr}${lineNumber}: `;
|
|
24
|
-
const prefixOffset = prefix.length;
|
|
25
|
-
const line = prefix + (sourceLine.split(/\r?\n?$/, 1)[0] || '');
|
|
26
|
-
const rangeOnThisLine = ({ start, end }) => ( new Range(
|
|
27
|
-
1,
|
|
28
|
-
(start ?? 1) + prefixOffset,
|
|
29
|
-
1,
|
|
30
|
-
(end ?? sourceLine.length + 1) + prefixOffset
|
|
31
|
-
));
|
|
32
|
-
const matchRange = match.rangeInPreview();
|
|
33
|
-
const matchIsSingleLine = matchRange.startLineNumber === matchRange.endLineNumber;
|
|
34
|
-
let lineRange;
|
|
35
|
-
if (matchIsSingleLine) {
|
|
36
|
-
lineRange = (rangeOnThisLine({ start: matchRange.startColumn, end: matchRange.endColumn }));
|
|
37
|
-
}
|
|
38
|
-
else if (i === 0) {
|
|
39
|
-
lineRange = (rangeOnThisLine({ start: matchRange.startColumn }));
|
|
40
|
-
}
|
|
41
|
-
else if (i === fullMatchLines.length - 1) {
|
|
42
|
-
lineRange = (rangeOnThisLine({ end: matchRange.endColumn }));
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
lineRange = (rangeOnThisLine({}));
|
|
46
|
-
}
|
|
47
|
-
results.push({ lineNumber: lineNumber, line, ranges: [lineRange] });
|
|
48
|
-
});
|
|
49
|
-
return results;
|
|
50
|
-
};
|
|
51
|
-
function fileMatchToSearchResultFormat(fileMatch, labelFormatter) {
|
|
52
|
-
const textSerializations = fileMatch.textMatches().length > 0 ? matchesToSearchResultFormat(fileMatch.resource, fileMatch.textMatches().sort(searchMatchComparer), fileMatch.context, labelFormatter) : undefined;
|
|
53
|
-
const cellSerializations = ( fileMatch.cellMatches().sort((a, b) => a.cellIndex - b.cellIndex).sort().filter(cellMatch => cellMatch.contentMatches.length > 0).map(
|
|
54
|
-
(cellMatch, index) => cellMatchToSearchResultFormat(cellMatch, labelFormatter, index === 0)
|
|
55
|
-
));
|
|
56
|
-
return [textSerializations, ...cellSerializations].filter(x => !!x);
|
|
57
|
-
}
|
|
58
|
-
function matchesToSearchResultFormat(resource, sortedMatches, matchContext, labelFormatter, shouldUseHeader = true) {
|
|
59
|
-
const longestLineNumber = ( sortedMatches[sortedMatches.length - 1].range().endLineNumber.toString()).length;
|
|
60
|
-
const text = shouldUseHeader ? [`${labelFormatter(resource)}:`] : [];
|
|
61
|
-
const matchRanges = [];
|
|
62
|
-
const targetLineNumberToOffset = {};
|
|
63
|
-
const context = [];
|
|
64
|
-
matchContext.forEach((line, lineNumber) => context.push({ line, lineNumber }));
|
|
65
|
-
context.sort((a, b) => a.lineNumber - b.lineNumber);
|
|
66
|
-
let lastLine = undefined;
|
|
67
|
-
const seenLines = ( new Set());
|
|
68
|
-
sortedMatches.forEach(match => {
|
|
69
|
-
matchToSearchResultFormat(match, longestLineNumber).forEach(match => {
|
|
70
|
-
if (!( seenLines.has(match.lineNumber))) {
|
|
71
|
-
while (context.length && context[0].lineNumber < +match.lineNumber) {
|
|
72
|
-
const { line, lineNumber } = context.shift();
|
|
73
|
-
if (lastLine !== undefined && lineNumber !== lastLine + 1) {
|
|
74
|
-
text.push('');
|
|
75
|
-
}
|
|
76
|
-
text.push(` ${' '.repeat(longestLineNumber - `${lineNumber}`.length)}${lineNumber} ${line}`);
|
|
77
|
-
lastLine = lineNumber;
|
|
78
|
-
}
|
|
79
|
-
targetLineNumberToOffset[match.lineNumber] = text.length;
|
|
80
|
-
seenLines.add(match.lineNumber);
|
|
81
|
-
text.push(match.line);
|
|
82
|
-
lastLine = +match.lineNumber;
|
|
83
|
-
}
|
|
84
|
-
matchRanges.push(...( match.ranges.map(translateRangeLines(targetLineNumberToOffset[match.lineNumber]))));
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
while (context.length) {
|
|
88
|
-
const { line, lineNumber } = context.shift();
|
|
89
|
-
text.push(` ${lineNumber} ${line}`);
|
|
90
|
-
}
|
|
91
|
-
return { text, matchRanges };
|
|
92
|
-
}
|
|
93
|
-
function cellMatchToSearchResultFormat(cellMatch, labelFormatter, shouldUseHeader) {
|
|
94
|
-
return matchesToSearchResultFormat(cellMatch.cell?.uri ?? cellMatch.parent.resource, cellMatch.contentMatches.sort(searchMatchComparer), cellMatch.context, labelFormatter, shouldUseHeader);
|
|
95
|
-
}
|
|
96
|
-
const contentPatternToSearchConfiguration = (pattern, includes, excludes, contextLines) => {
|
|
97
|
-
return {
|
|
98
|
-
query: pattern.contentPattern.pattern,
|
|
99
|
-
isRegexp: !!pattern.contentPattern.isRegExp,
|
|
100
|
-
isCaseSensitive: !!pattern.contentPattern.isCaseSensitive,
|
|
101
|
-
matchWholeWord: !!pattern.contentPattern.isWordMatch,
|
|
102
|
-
filesToExclude: excludes, filesToInclude: includes,
|
|
103
|
-
showIncludesExcludes: !!(includes || excludes || pattern?.userDisabledExcludesAndIgnoreFiles),
|
|
104
|
-
useExcludeSettingsAndIgnoreFiles: (pattern?.userDisabledExcludesAndIgnoreFiles === undefined ? true : !pattern.userDisabledExcludesAndIgnoreFiles),
|
|
105
|
-
contextLines,
|
|
106
|
-
onlyOpenEditors: !!pattern.onlyOpenEditors,
|
|
107
|
-
notebookSearchConfig: {
|
|
108
|
-
includeMarkupInput: !!pattern.contentPattern.notebookInfo?.isInNotebookMarkdownInput,
|
|
109
|
-
includeMarkupPreview: !!pattern.contentPattern.notebookInfo?.isInNotebookMarkdownPreview,
|
|
110
|
-
includeCodeInput: !!pattern.contentPattern.notebookInfo?.isInNotebookCellInput,
|
|
111
|
-
includeOutput: !!pattern.contentPattern.notebookInfo?.isInNotebookCellOutput,
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
};
|
|
115
|
-
const serializeSearchConfiguration = (config) => {
|
|
116
|
-
const removeNullFalseAndUndefined = (a) => a.filter(a => a !== false && a !== null && a !== undefined);
|
|
117
|
-
const escapeNewlines = (str) => str.replace(/\\/g, '\\\\').replace(/\n/g, '\\n');
|
|
118
|
-
return removeNullFalseAndUndefined([
|
|
119
|
-
`# Query: ${escapeNewlines(config.query ?? '')}`,
|
|
120
|
-
(config.isCaseSensitive || config.matchWholeWord || config.isRegexp || config.useExcludeSettingsAndIgnoreFiles === false)
|
|
121
|
-
&& `# Flags: ${coalesce([
|
|
122
|
-
config.isCaseSensitive && 'CaseSensitive',
|
|
123
|
-
config.matchWholeWord && 'WordMatch',
|
|
124
|
-
config.isRegexp && 'RegExp',
|
|
125
|
-
config.onlyOpenEditors && 'OpenEditors',
|
|
126
|
-
(config.useExcludeSettingsAndIgnoreFiles === false) && 'IgnoreExcludeSettings'
|
|
127
|
-
]).join(' ')}`,
|
|
128
|
-
config.filesToInclude ? `# Including: ${config.filesToInclude}` : undefined,
|
|
129
|
-
config.filesToExclude ? `# Excluding: ${config.filesToExclude}` : undefined,
|
|
130
|
-
config.contextLines ? `# ContextLines: ${config.contextLines}` : undefined,
|
|
131
|
-
''
|
|
132
|
-
]).join(lineDelimiter);
|
|
133
|
-
};
|
|
134
|
-
const defaultSearchConfig = () => ({
|
|
135
|
-
query: '',
|
|
136
|
-
filesToInclude: '',
|
|
137
|
-
filesToExclude: '',
|
|
138
|
-
isRegexp: false,
|
|
139
|
-
isCaseSensitive: false,
|
|
140
|
-
useExcludeSettingsAndIgnoreFiles: true,
|
|
141
|
-
matchWholeWord: false,
|
|
142
|
-
contextLines: 0,
|
|
143
|
-
showIncludesExcludes: false,
|
|
144
|
-
onlyOpenEditors: false,
|
|
145
|
-
notebookSearchConfig: {
|
|
146
|
-
includeMarkupInput: true,
|
|
147
|
-
includeMarkupPreview: false,
|
|
148
|
-
includeCodeInput: true,
|
|
149
|
-
includeOutput: true,
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
const extractSearchQueryFromLines = (lines) => {
|
|
153
|
-
const query = defaultSearchConfig();
|
|
154
|
-
const unescapeNewlines = (str) => {
|
|
155
|
-
let out = '';
|
|
156
|
-
for (let i = 0; i < str.length; i++) {
|
|
157
|
-
if (str[i] === '\\') {
|
|
158
|
-
i++;
|
|
159
|
-
const escaped = str[i];
|
|
160
|
-
if (escaped === 'n') {
|
|
161
|
-
out += '\n';
|
|
162
|
-
}
|
|
163
|
-
else if (escaped === '\\') {
|
|
164
|
-
out += '\\';
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
throw Error(localizeWithPath('vs/workbench/contrib/searchEditor/browser/searchEditorSerialization', 'invalidQueryStringError', "All backslashes in Query string must be escaped (\\\\)"));
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
out += str[i];
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return out;
|
|
175
|
-
};
|
|
176
|
-
const parseYML = /^# ([^:]*): (.*)$/;
|
|
177
|
-
for (const line of lines) {
|
|
178
|
-
const parsed = parseYML.exec(line);
|
|
179
|
-
if (!parsed) {
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
const [, key, value] = parsed;
|
|
183
|
-
switch (key) {
|
|
184
|
-
case 'Query':
|
|
185
|
-
query.query = unescapeNewlines(value);
|
|
186
|
-
break;
|
|
187
|
-
case 'Including':
|
|
188
|
-
query.filesToInclude = value;
|
|
189
|
-
break;
|
|
190
|
-
case 'Excluding':
|
|
191
|
-
query.filesToExclude = value;
|
|
192
|
-
break;
|
|
193
|
-
case 'ContextLines':
|
|
194
|
-
query.contextLines = +value;
|
|
195
|
-
break;
|
|
196
|
-
case 'Flags': {
|
|
197
|
-
query.isRegexp = value.indexOf('RegExp') !== -1;
|
|
198
|
-
query.isCaseSensitive = value.indexOf('CaseSensitive') !== -1;
|
|
199
|
-
query.useExcludeSettingsAndIgnoreFiles = value.indexOf('IgnoreExcludeSettings') === -1;
|
|
200
|
-
query.matchWholeWord = value.indexOf('WordMatch') !== -1;
|
|
201
|
-
query.onlyOpenEditors = value.indexOf('OpenEditors') !== -1;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
query.showIncludesExcludes = !!(query.filesToInclude || query.filesToExclude || !query.useExcludeSettingsAndIgnoreFiles);
|
|
206
|
-
return query;
|
|
207
|
-
};
|
|
208
|
-
const serializeSearchResultForEditor = (searchResult, rawIncludePattern, rawExcludePattern, contextLines, labelFormatter, sortOrder, limitHit) => {
|
|
209
|
-
if (!searchResult.query) {
|
|
210
|
-
throw Error('Internal Error: Expected query, got null');
|
|
211
|
-
}
|
|
212
|
-
const config = contentPatternToSearchConfiguration(searchResult.query, rawIncludePattern, rawExcludePattern, contextLines);
|
|
213
|
-
const filecount = searchResult.fileCount() > 1 ? ( localizeWithPath(
|
|
214
|
-
'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization',
|
|
215
|
-
'numFiles',
|
|
216
|
-
"{0} files",
|
|
217
|
-
searchResult.fileCount()
|
|
218
|
-
)) : ( localizeWithPath(
|
|
219
|
-
'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization',
|
|
220
|
-
'oneFile',
|
|
221
|
-
"1 file"
|
|
222
|
-
));
|
|
223
|
-
const resultcount = searchResult.count() > 1 ? ( localizeWithPath(
|
|
224
|
-
'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization',
|
|
225
|
-
'numResults',
|
|
226
|
-
"{0} results",
|
|
227
|
-
searchResult.count()
|
|
228
|
-
)) : ( localizeWithPath(
|
|
229
|
-
'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization',
|
|
230
|
-
'oneResult',
|
|
231
|
-
"1 result"
|
|
232
|
-
));
|
|
233
|
-
const info = [
|
|
234
|
-
searchResult.count()
|
|
235
|
-
? `${resultcount} - ${filecount}`
|
|
236
|
-
: ( localizeWithPath(
|
|
237
|
-
'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization',
|
|
238
|
-
'noResults',
|
|
239
|
-
"No Results"
|
|
240
|
-
)),
|
|
241
|
-
];
|
|
242
|
-
if (limitHit) {
|
|
243
|
-
info.push(( localizeWithPath(
|
|
244
|
-
'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization',
|
|
245
|
-
'searchMaxResultsWarning',
|
|
246
|
-
"The result set only contains a subset of all matches. Be more specific in your search to narrow down the results."
|
|
247
|
-
)));
|
|
248
|
-
}
|
|
249
|
-
info.push('');
|
|
250
|
-
const matchComparer = (a, b) => searchMatchComparer(a, b, sortOrder);
|
|
251
|
-
const allResults = flattenSearchResultSerializations(flatten(( searchResult.folderMatches().sort(matchComparer)
|
|
252
|
-
.map(folderMatch => folderMatch.allDownstreamFileMatches().sort(matchComparer)
|
|
253
|
-
.flatMap(fileMatch => fileMatchToSearchResultFormat(fileMatch, labelFormatter))))));
|
|
254
|
-
return {
|
|
255
|
-
matchRanges: ( allResults.matchRanges.map(translateRangeLines(info.length))),
|
|
256
|
-
text: info.concat(allResults.text).join(lineDelimiter),
|
|
257
|
-
config
|
|
258
|
-
};
|
|
259
|
-
};
|
|
260
|
-
const flattenSearchResultSerializations = (serializations) => {
|
|
261
|
-
const text = [];
|
|
262
|
-
const matchRanges = [];
|
|
263
|
-
serializations.forEach(serialized => {
|
|
264
|
-
( serialized.matchRanges.map(translateRangeLines(text.length))).forEach(range => matchRanges.push(range));
|
|
265
|
-
serialized.text.forEach(line => text.push(line));
|
|
266
|
-
text.push('');
|
|
267
|
-
});
|
|
268
|
-
return { text, matchRanges };
|
|
269
|
-
};
|
|
270
|
-
const parseSavedSearchEditor = async (accessor, resource) => {
|
|
271
|
-
const textFileService = accessor.get(ITextFileService);
|
|
272
|
-
const text = (await textFileService.read(resource)).value;
|
|
273
|
-
return parseSerializedSearchEditor(text);
|
|
274
|
-
};
|
|
275
|
-
const parseSerializedSearchEditor = (text) => {
|
|
276
|
-
const headerlines = [];
|
|
277
|
-
const bodylines = [];
|
|
278
|
-
let inHeader = true;
|
|
279
|
-
for (const line of text.split(/\r?\n/g)) {
|
|
280
|
-
if (inHeader) {
|
|
281
|
-
headerlines.push(line);
|
|
282
|
-
if (line === '') {
|
|
283
|
-
inHeader = false;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
bodylines.push(line);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return { config: extractSearchQueryFromLines(headerlines), text: bodylines.join('\n') };
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
export { defaultSearchConfig, extractSearchQueryFromLines, parseSavedSearchEditor, parseSerializedSearchEditor, serializeSearchConfiguration, serializeSearchResultForEditor };
|
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
|
|
2
|
-
import { coalesce, flatten, uniqueFilter } from 'vscode/vscode/vs/base/common/arrays';
|
|
3
|
-
import { DeferredPromise } from 'vscode/vscode/vs/base/common/async';
|
|
4
|
-
import { CancellationError } from 'vscode/vscode/vs/base/common/errors';
|
|
5
|
-
import { Disposable, toDisposable } from 'vscode/vscode/vs/base/common/lifecycle';
|
|
6
|
-
import { ResourceMap, ResourceSet } from 'vscode/vscode/vs/base/common/map';
|
|
7
|
-
import { Schemas } from 'vscode/vscode/vs/base/common/network';
|
|
8
|
-
import { StopWatch } from 'vscode/vscode/vs/base/common/stopwatch';
|
|
9
|
-
import { isNumber } from 'vscode/vscode/vs/base/common/types';
|
|
10
|
-
import { IModelService } from 'vscode/vscode/vs/editor/common/services/model';
|
|
11
|
-
import { IFileService } from 'vscode/vscode/vs/platform/files/common/files';
|
|
12
|
-
import { ILogService } from 'vscode/vscode/vs/platform/log/common/log';
|
|
13
|
-
import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
|
|
14
|
-
import { IUriIdentityService } from 'vscode/vscode/vs/platform/uriIdentity/common/uriIdentity';
|
|
15
|
-
import { EditorResourceAccessor, SideBySideEditor } from 'vscode/vscode/vs/workbench/common/editor';
|
|
16
|
-
import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
|
|
17
|
-
import { IExtensionService } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions';
|
|
18
|
-
import { deserializeSearchError, SearchErrorCode, SEARCH_RESULT_LANGUAGE_ID, FileMatch, pathIncludedInQuery, isFileMatch, isProgressMessage } from 'vscode/vscode/vs/workbench/services/search/common/search';
|
|
19
|
-
import { editorMatchesToTextSearchResults, getTextSearchMatchWithModelContext } from 'vscode/vscode/vs/workbench/services/search/common/searchHelpers';
|
|
20
|
-
|
|
21
|
-
let SearchService = class SearchService extends Disposable {
|
|
22
|
-
constructor(modelService, editorService, telemetryService, logService, extensionService, fileService, uriIdentityService) {
|
|
23
|
-
super();
|
|
24
|
-
this.modelService = modelService;
|
|
25
|
-
this.editorService = editorService;
|
|
26
|
-
this.telemetryService = telemetryService;
|
|
27
|
-
this.logService = logService;
|
|
28
|
-
this.extensionService = extensionService;
|
|
29
|
-
this.fileService = fileService;
|
|
30
|
-
this.uriIdentityService = uriIdentityService;
|
|
31
|
-
this.fileSearchProviders = ( new Map());
|
|
32
|
-
this.textSearchProviders = ( new Map());
|
|
33
|
-
this.deferredFileSearchesByScheme = ( new Map());
|
|
34
|
-
this.deferredTextSearchesByScheme = ( new Map());
|
|
35
|
-
this.loggedSchemesMissingProviders = ( new Set());
|
|
36
|
-
}
|
|
37
|
-
registerSearchResultProvider(scheme, type, provider) {
|
|
38
|
-
let list;
|
|
39
|
-
let deferredMap;
|
|
40
|
-
if (type === 0 ) {
|
|
41
|
-
list = this.fileSearchProviders;
|
|
42
|
-
deferredMap = this.deferredFileSearchesByScheme;
|
|
43
|
-
}
|
|
44
|
-
else if (type === 1 ) {
|
|
45
|
-
list = this.textSearchProviders;
|
|
46
|
-
deferredMap = this.deferredTextSearchesByScheme;
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
throw new Error('Unknown SearchProviderType');
|
|
50
|
-
}
|
|
51
|
-
list.set(scheme, provider);
|
|
52
|
-
if (( deferredMap.has(scheme))) {
|
|
53
|
-
deferredMap.get(scheme).complete(provider);
|
|
54
|
-
deferredMap.delete(scheme);
|
|
55
|
-
}
|
|
56
|
-
return toDisposable(() => {
|
|
57
|
-
list.delete(scheme);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
async textSearch(query, token, onProgress) {
|
|
61
|
-
const results = this.textSearchSplitSyncAsync(query, token, onProgress);
|
|
62
|
-
const openEditorResults = results.syncResults;
|
|
63
|
-
const otherResults = await results.asyncResults;
|
|
64
|
-
return {
|
|
65
|
-
limitHit: otherResults.limitHit || openEditorResults.limitHit,
|
|
66
|
-
results: [...otherResults.results, ...openEditorResults.results],
|
|
67
|
-
messages: [...otherResults.messages, ...openEditorResults.messages]
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
textSearchSplitSyncAsync(query, token, onProgress, notebookFilesToIgnore, asyncNotebookFilesToIgnore) {
|
|
71
|
-
const openEditorResults = this.getOpenEditorResults(query);
|
|
72
|
-
if (onProgress) {
|
|
73
|
-
coalesce([...( openEditorResults.results.values())]).filter(e => !(notebookFilesToIgnore && ( notebookFilesToIgnore.has(e.resource)))).forEach(onProgress);
|
|
74
|
-
}
|
|
75
|
-
const syncResults = {
|
|
76
|
-
results: coalesce([...( openEditorResults.results.values())]),
|
|
77
|
-
limitHit: openEditorResults.limitHit ?? false,
|
|
78
|
-
messages: []
|
|
79
|
-
};
|
|
80
|
-
const getAsyncResults = async () => {
|
|
81
|
-
const resolvedAsyncNotebookFilesToIgnore = (await asyncNotebookFilesToIgnore) ?? ( new ResourceSet());
|
|
82
|
-
const onProviderProgress = (progress) => {
|
|
83
|
-
if (isFileMatch(progress)) {
|
|
84
|
-
if (!( openEditorResults.results.has(progress.resource)) && !( resolvedAsyncNotebookFilesToIgnore.has(progress.resource)) && onProgress) {
|
|
85
|
-
onProgress(progress);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
else if (onProgress) {
|
|
89
|
-
onProgress(progress);
|
|
90
|
-
}
|
|
91
|
-
if (isProgressMessage(progress)) {
|
|
92
|
-
this.logService.debug('SearchService#search', progress.message);
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
return await this.doSearch(query, token, onProviderProgress);
|
|
96
|
-
};
|
|
97
|
-
return {
|
|
98
|
-
syncResults,
|
|
99
|
-
asyncResults: getAsyncResults()
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
fileSearch(query, token) {
|
|
103
|
-
return this.doSearch(query, token);
|
|
104
|
-
}
|
|
105
|
-
doSearch(query, token, onProgress) {
|
|
106
|
-
this.logService.trace('SearchService#search', JSON.stringify(query));
|
|
107
|
-
const schemesInQuery = this.getSchemesInQuery(query);
|
|
108
|
-
const providerActivations = [Promise.resolve(null)];
|
|
109
|
-
schemesInQuery.forEach(scheme => providerActivations.push(this.extensionService.activateByEvent(`onSearch:${scheme}`)));
|
|
110
|
-
providerActivations.push(this.extensionService.activateByEvent('onSearch:file'));
|
|
111
|
-
const providerPromise = (async () => {
|
|
112
|
-
await Promise.all(providerActivations);
|
|
113
|
-
await this.extensionService.whenInstalledExtensionsRegistered();
|
|
114
|
-
if (token && token.isCancellationRequested) {
|
|
115
|
-
return Promise.reject(( new CancellationError()));
|
|
116
|
-
}
|
|
117
|
-
const progressCallback = (item) => {
|
|
118
|
-
if (token && token.isCancellationRequested) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
onProgress?.(item);
|
|
122
|
-
};
|
|
123
|
-
const exists = await Promise.all(( query.folderQueries.map(query => this.fileService.exists(query.folder))));
|
|
124
|
-
query.folderQueries = query.folderQueries.filter((_, i) => exists[i]);
|
|
125
|
-
let completes = await this.searchWithProviders(query, progressCallback, token);
|
|
126
|
-
completes = coalesce(completes);
|
|
127
|
-
if (!completes.length) {
|
|
128
|
-
return {
|
|
129
|
-
limitHit: false,
|
|
130
|
-
results: [],
|
|
131
|
-
messages: [],
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
return {
|
|
135
|
-
limitHit: completes[0] && completes[0].limitHit,
|
|
136
|
-
stats: completes[0].stats,
|
|
137
|
-
messages: coalesce(flatten(( completes.map(i => i.messages)))).filter(uniqueFilter(message => message.type + message.text + message.trusted)),
|
|
138
|
-
results: flatten(( completes.map((c) => c.results)))
|
|
139
|
-
};
|
|
140
|
-
})();
|
|
141
|
-
return ( new Promise((resolve, reject) => {
|
|
142
|
-
if (token) {
|
|
143
|
-
token.onCancellationRequested(() => {
|
|
144
|
-
reject(( new CancellationError()));
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
providerPromise.then(resolve, reject);
|
|
148
|
-
}));
|
|
149
|
-
}
|
|
150
|
-
getSchemesInQuery(query) {
|
|
151
|
-
const schemes = ( new Set());
|
|
152
|
-
query.folderQueries?.forEach(fq => schemes.add(fq.folder.scheme));
|
|
153
|
-
query.extraFileResources?.forEach(extraFile => schemes.add(extraFile.scheme));
|
|
154
|
-
return schemes;
|
|
155
|
-
}
|
|
156
|
-
async waitForProvider(queryType, scheme) {
|
|
157
|
-
const deferredMap = queryType === 1 ?
|
|
158
|
-
this.deferredFileSearchesByScheme :
|
|
159
|
-
this.deferredTextSearchesByScheme;
|
|
160
|
-
if (( deferredMap.has(scheme))) {
|
|
161
|
-
return deferredMap.get(scheme).p;
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
const deferred = ( new DeferredPromise());
|
|
165
|
-
deferredMap.set(scheme, deferred);
|
|
166
|
-
return deferred.p;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
async searchWithProviders(query, onProviderProgress, token) {
|
|
170
|
-
const e2eSW = StopWatch.create(false);
|
|
171
|
-
const searchPs = [];
|
|
172
|
-
const fqs = this.groupFolderQueriesByScheme(query);
|
|
173
|
-
const someSchemeHasProvider = ( [...( fqs.keys())].some(scheme => {
|
|
174
|
-
return query.type === 1 ?
|
|
175
|
-
( this.fileSearchProviders.has(scheme)) :
|
|
176
|
-
( this.textSearchProviders.has(scheme));
|
|
177
|
-
}));
|
|
178
|
-
await Promise.all(( [...( fqs.keys())].map(async (scheme) => {
|
|
179
|
-
const schemeFQs = fqs.get(scheme);
|
|
180
|
-
let provider = query.type === 1 ?
|
|
181
|
-
this.fileSearchProviders.get(scheme) :
|
|
182
|
-
this.textSearchProviders.get(scheme);
|
|
183
|
-
if (!provider) {
|
|
184
|
-
if (someSchemeHasProvider) {
|
|
185
|
-
if (!( this.loggedSchemesMissingProviders.has(scheme))) {
|
|
186
|
-
this.logService.warn(`No search provider registered for scheme: ${scheme}. Another scheme has a provider, not waiting for ${scheme}`);
|
|
187
|
-
this.loggedSchemesMissingProviders.add(scheme);
|
|
188
|
-
}
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
if (!( this.loggedSchemesMissingProviders.has(scheme))) {
|
|
193
|
-
this.logService.warn(`No search provider registered for scheme: ${scheme}, waiting`);
|
|
194
|
-
this.loggedSchemesMissingProviders.add(scheme);
|
|
195
|
-
}
|
|
196
|
-
provider = await this.waitForProvider(query.type, scheme);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
const oneSchemeQuery = {
|
|
200
|
-
...query,
|
|
201
|
-
...{
|
|
202
|
-
folderQueries: schemeFQs
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
searchPs.push(query.type === 1 ?
|
|
206
|
-
provider.fileSearch(oneSchemeQuery, token) :
|
|
207
|
-
provider.textSearch(oneSchemeQuery, onProviderProgress, token));
|
|
208
|
-
})));
|
|
209
|
-
return Promise.all(searchPs).then(completes => {
|
|
210
|
-
const endToEndTime = e2eSW.elapsed();
|
|
211
|
-
this.logService.trace(`SearchService#search: ${endToEndTime}ms`);
|
|
212
|
-
completes.forEach(complete => {
|
|
213
|
-
this.sendTelemetry(query, endToEndTime, complete);
|
|
214
|
-
});
|
|
215
|
-
return completes;
|
|
216
|
-
}, err => {
|
|
217
|
-
const endToEndTime = e2eSW.elapsed();
|
|
218
|
-
this.logService.trace(`SearchService#search: ${endToEndTime}ms`);
|
|
219
|
-
const searchError = deserializeSearchError(err);
|
|
220
|
-
this.logService.trace(`SearchService#searchError: ${searchError.message}`);
|
|
221
|
-
this.sendTelemetry(query, endToEndTime, undefined, searchError);
|
|
222
|
-
throw searchError;
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
groupFolderQueriesByScheme(query) {
|
|
226
|
-
const queries = ( new Map());
|
|
227
|
-
query.folderQueries.forEach(fq => {
|
|
228
|
-
const schemeFQs = queries.get(fq.folder.scheme) || [];
|
|
229
|
-
schemeFQs.push(fq);
|
|
230
|
-
queries.set(fq.folder.scheme, schemeFQs);
|
|
231
|
-
});
|
|
232
|
-
return queries;
|
|
233
|
-
}
|
|
234
|
-
sendTelemetry(query, endToEndTime, complete, err) {
|
|
235
|
-
const fileSchemeOnly = query.folderQueries.every(fq => fq.folder.scheme === Schemas.file);
|
|
236
|
-
const otherSchemeOnly = query.folderQueries.every(fq => fq.folder.scheme !== Schemas.file);
|
|
237
|
-
const scheme = fileSchemeOnly ? Schemas.file :
|
|
238
|
-
otherSchemeOnly ? 'other' :
|
|
239
|
-
'mixed';
|
|
240
|
-
if (query.type === 1 && complete && complete.stats) {
|
|
241
|
-
const fileSearchStats = complete.stats;
|
|
242
|
-
if (fileSearchStats.fromCache) {
|
|
243
|
-
const cacheStats = fileSearchStats.detailStats;
|
|
244
|
-
this.telemetryService.publicLog2('cachedSearchComplete', {
|
|
245
|
-
reason: query._reason,
|
|
246
|
-
resultCount: fileSearchStats.resultCount,
|
|
247
|
-
workspaceFolderCount: query.folderQueries.length,
|
|
248
|
-
endToEndTime: endToEndTime,
|
|
249
|
-
sortingTime: fileSearchStats.sortingTime,
|
|
250
|
-
cacheWasResolved: cacheStats.cacheWasResolved,
|
|
251
|
-
cacheLookupTime: cacheStats.cacheLookupTime,
|
|
252
|
-
cacheFilterTime: cacheStats.cacheFilterTime,
|
|
253
|
-
cacheEntryCount: cacheStats.cacheEntryCount,
|
|
254
|
-
scheme
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
const searchEngineStats = fileSearchStats.detailStats;
|
|
259
|
-
this.telemetryService.publicLog2('searchComplete', {
|
|
260
|
-
reason: query._reason,
|
|
261
|
-
resultCount: fileSearchStats.resultCount,
|
|
262
|
-
workspaceFolderCount: query.folderQueries.length,
|
|
263
|
-
endToEndTime: endToEndTime,
|
|
264
|
-
sortingTime: fileSearchStats.sortingTime,
|
|
265
|
-
fileWalkTime: searchEngineStats.fileWalkTime,
|
|
266
|
-
directoriesWalked: searchEngineStats.directoriesWalked,
|
|
267
|
-
filesWalked: searchEngineStats.filesWalked,
|
|
268
|
-
cmdTime: searchEngineStats.cmdTime,
|
|
269
|
-
cmdResultCount: searchEngineStats.cmdResultCount,
|
|
270
|
-
scheme
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
else if (query.type === 2 ) {
|
|
275
|
-
let errorType;
|
|
276
|
-
if (err) {
|
|
277
|
-
errorType = err.code === SearchErrorCode.regexParseError ? 'regex' :
|
|
278
|
-
err.code === SearchErrorCode.unknownEncoding ? 'encoding' :
|
|
279
|
-
err.code === SearchErrorCode.globParseError ? 'glob' :
|
|
280
|
-
err.code === SearchErrorCode.invalidLiteral ? 'literal' :
|
|
281
|
-
err.code === SearchErrorCode.other ? 'other' :
|
|
282
|
-
err.code === SearchErrorCode.canceled ? 'canceled' :
|
|
283
|
-
'unknown';
|
|
284
|
-
}
|
|
285
|
-
this.telemetryService.publicLog2('textSearchComplete', {
|
|
286
|
-
reason: query._reason,
|
|
287
|
-
workspaceFolderCount: query.folderQueries.length,
|
|
288
|
-
endToEndTime: endToEndTime,
|
|
289
|
-
scheme,
|
|
290
|
-
error: errorType,
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
getOpenEditorResults(query) {
|
|
295
|
-
const openEditorResults = ( new ResourceMap(uri => this.uriIdentityService.extUri.getComparisonKey(uri)));
|
|
296
|
-
let limitHit = false;
|
|
297
|
-
if (query.type === 2 ) {
|
|
298
|
-
const canonicalToOriginalResources = ( new ResourceMap());
|
|
299
|
-
for (const editorInput of this.editorService.editors) {
|
|
300
|
-
const canonical = EditorResourceAccessor.getCanonicalUri(editorInput, { supportSideBySide: SideBySideEditor.PRIMARY });
|
|
301
|
-
const original = EditorResourceAccessor.getOriginalUri(editorInput, { supportSideBySide: SideBySideEditor.PRIMARY });
|
|
302
|
-
if (canonical) {
|
|
303
|
-
canonicalToOriginalResources.set(canonical, original ?? canonical);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
const models = this.modelService.getModels();
|
|
307
|
-
models.forEach((model) => {
|
|
308
|
-
const resource = model.uri;
|
|
309
|
-
if (!resource) {
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
if (limitHit) {
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
const originalResource = canonicalToOriginalResources.get(resource);
|
|
316
|
-
if (!originalResource) {
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
if (model.getLanguageId() === SEARCH_RESULT_LANGUAGE_ID && !(query.includePattern && query.includePattern['**/*.code-search'])) {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
if (originalResource.scheme !== Schemas.untitled && !this.fileService.hasProvider(originalResource)) {
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
if (originalResource.scheme === 'git') {
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
if (!this.matches(originalResource, query)) {
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
const askMax = isNumber(query.maxResults) ? query.maxResults + 1 : Number.MAX_SAFE_INTEGER;
|
|
332
|
-
let matches = model.findMatches(query.contentPattern.pattern, false, !!query.contentPattern.isRegExp, !!query.contentPattern.isCaseSensitive, query.contentPattern.isWordMatch ? query.contentPattern.wordSeparators : null, false, askMax);
|
|
333
|
-
if (matches.length) {
|
|
334
|
-
if (askMax && matches.length >= askMax) {
|
|
335
|
-
limitHit = true;
|
|
336
|
-
matches = matches.slice(0, askMax - 1);
|
|
337
|
-
}
|
|
338
|
-
const fileMatch = ( new FileMatch(originalResource));
|
|
339
|
-
openEditorResults.set(originalResource, fileMatch);
|
|
340
|
-
const textSearchResults = editorMatchesToTextSearchResults(matches, model, query.previewOptions);
|
|
341
|
-
fileMatch.results = getTextSearchMatchWithModelContext(textSearchResults, model, query);
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
openEditorResults.set(originalResource, null);
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
return {
|
|
349
|
-
results: openEditorResults,
|
|
350
|
-
limitHit
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
matches(resource, query) {
|
|
354
|
-
return pathIncludedInQuery(query, resource.fsPath);
|
|
355
|
-
}
|
|
356
|
-
async clearCache(cacheKey) {
|
|
357
|
-
const clearPs = ( Array.from(( this.fileSearchProviders.values()))
|
|
358
|
-
.map(provider => provider && provider.clearCache(cacheKey)));
|
|
359
|
-
await Promise.all(clearPs);
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
SearchService = ( __decorate([
|
|
363
|
-
( __param(0, IModelService)),
|
|
364
|
-
( __param(1, IEditorService)),
|
|
365
|
-
( __param(2, ITelemetryService)),
|
|
366
|
-
( __param(3, ILogService)),
|
|
367
|
-
( __param(4, IExtensionService)),
|
|
368
|
-
( __param(5, IFileService)),
|
|
369
|
-
( __param(6, IUriIdentityService))
|
|
370
|
-
], SearchService));
|
|
371
|
-
|
|
372
|
-
export { SearchService };
|