blob: 26c125116f5257d15df3d6b6ccae9ae3539fe0d5 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
Tim van der Lippe8987f8f2020-01-03 15:03:1628
Blink Reformat4c46d092018-04-07 15:32:3729/**
30 * @implements {Search.SearchScope}
31 */
Paul Lewis39944952020-01-22 15:45:1832export class SourcesSearchScope {
Blink Reformat4c46d092018-04-07 15:32:3733 constructor() {
34 // FIXME: Add title once it is used by search controller.
35 this._searchId = 0;
36 /** @type {!Array<!Workspace.UISourceCode>} */
37 this._searchResultCandidates = [];
38 /** @type {?function(!Search.SearchResult)} */
39 this._searchResultCallback = null;
40 /** @type {?function(boolean)} */
41 this._searchFinishedCallback = null;
42 /** @type {?Workspace.ProjectSearchConfig} */
43 this._searchConfig = null;
44 }
45
46 /**
47 * @param {!Workspace.UISourceCode} uiSourceCode1
48 * @param {!Workspace.UISourceCode} uiSourceCode2
49 * @return {number}
50 */
51 static _filesComparator(uiSourceCode1, uiSourceCode2) {
Tim van der Lippe1d6e57a2019-09-30 11:55:3452 if (uiSourceCode1.isDirty() && !uiSourceCode2.isDirty()) {
Blink Reformat4c46d092018-04-07 15:32:3753 return -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:3454 }
55 if (!uiSourceCode1.isDirty() && uiSourceCode2.isDirty()) {
Blink Reformat4c46d092018-04-07 15:32:3756 return 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:3457 }
Joel Einbinderef3555d2018-12-04 02:14:4458 const isFileSystem1 = uiSourceCode1.project().type() === Workspace.projectTypes.FileSystem &&
59 !Persistence.persistence.binding(uiSourceCode1);
60 const isFileSystem2 = uiSourceCode2.project().type() === Workspace.projectTypes.FileSystem &&
61 !Persistence.persistence.binding(uiSourceCode2);
Tim van der Lippe1d6e57a2019-09-30 11:55:3462 if (isFileSystem1 !== isFileSystem2) {
Joel Einbinderef3555d2018-12-04 02:14:4463 return isFileSystem1 ? 1 : -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:3464 }
Blink Reformat4c46d092018-04-07 15:32:3765 const url1 = uiSourceCode1.url();
66 const url2 = uiSourceCode2.url();
Tim van der Lippe1d6e57a2019-09-30 11:55:3467 if (url1 && !url2) {
Blink Reformat4c46d092018-04-07 15:32:3768 return -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:3469 }
70 if (!url1 && url2) {
Blink Reformat4c46d092018-04-07 15:32:3771 return 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:3472 }
Blink Reformat4c46d092018-04-07 15:32:3773 return String.naturalOrderComparator(uiSourceCode1.fullDisplayName(), uiSourceCode2.fullDisplayName());
74 }
75
76 /**
77 * @override
78 * @param {!Common.Progress} progress
79 */
80 performIndexing(progress) {
81 this.stopSearch();
82
83 const projects = this._projects();
84 const compositeProgress = new Common.CompositeProgress(progress);
85 for (let i = 0; i < projects.length; ++i) {
86 const project = projects[i];
87 const projectProgress = compositeProgress.createSubProgress(project.uiSourceCodes().length);
88 project.indexContent(projectProgress);
89 }
90 }
91
92 /**
93 * @return {!Array.<!Workspace.Project>}
94 */
95 _projects() {
96 const searchInAnonymousAndContentScripts = Common.moduleSetting('searchInAnonymousAndContentScripts').get();
97
98 return Workspace.workspace.projects().filter(project => {
Tim van der Lippe1d6e57a2019-09-30 11:55:3499 if (project.type() === Workspace.projectTypes.Service) {
Blink Reformat4c46d092018-04-07 15:32:37100 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34101 }
102 if (!searchInAnonymousAndContentScripts && project.isServiceProject()) {
Blink Reformat4c46d092018-04-07 15:32:37103 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34104 }
105 if (!searchInAnonymousAndContentScripts && project.type() === Workspace.projectTypes.ContentScripts) {
Blink Reformat4c46d092018-04-07 15:32:37106 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34107 }
Blink Reformat4c46d092018-04-07 15:32:37108 return true;
109 });
110 }
111
112 /**
113 * @override
114 * @param {!Workspace.ProjectSearchConfig} searchConfig
115 * @param {!Common.Progress} progress
116 * @param {function(!Search.SearchResult)} searchResultCallback
117 * @param {function(boolean)} searchFinishedCallback
118 */
119 performSearch(searchConfig, progress, searchResultCallback, searchFinishedCallback) {
120 this.stopSearch();
121 this._searchResultCandidates = [];
122 this._searchResultCallback = searchResultCallback;
123 this._searchFinishedCallback = searchFinishedCallback;
124 this._searchConfig = searchConfig;
125
126 const promises = [];
127 const compositeProgress = new Common.CompositeProgress(progress);
128 const searchContentProgress = compositeProgress.createSubProgress();
129 const findMatchingFilesProgress = new Common.CompositeProgress(compositeProgress.createSubProgress());
130 for (const project of this._projects()) {
131 const weight = project.uiSourceCodes().length;
132 const findMatchingFilesInProjectProgress = findMatchingFilesProgress.createSubProgress(weight);
133 const filesMathingFileQuery = this._projectFilesMatchingFileQuery(project, searchConfig);
134 const promise =
135 project
136 .findFilesMatchingSearchRequest(searchConfig, filesMathingFileQuery, findMatchingFilesInProjectProgress)
137 .then(this._processMatchingFilesForProject.bind(
138 this, this._searchId, project, searchConfig, filesMathingFileQuery));
139 promises.push(promise);
140 }
141
142 Promise.all(promises).then(this._processMatchingFiles.bind(
143 this, this._searchId, searchContentProgress, this._searchFinishedCallback.bind(this, true)));
144 }
145
146 /**
147 * @param {!Workspace.Project} project
148 * @param {!Workspace.ProjectSearchConfig} searchConfig
149 * @param {boolean=} dirtyOnly
150 * @return {!Array.<string>}
151 */
152 _projectFilesMatchingFileQuery(project, searchConfig, dirtyOnly) {
153 const result = [];
154 const uiSourceCodes = project.uiSourceCodes();
155 for (let i = 0; i < uiSourceCodes.length; ++i) {
156 const uiSourceCode = uiSourceCodes[i];
Tim van der Lippe1d6e57a2019-09-30 11:55:34157 if (!uiSourceCode.contentType().isTextType()) {
Blink Reformat4c46d092018-04-07 15:32:37158 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34159 }
Blink Reformat4c46d092018-04-07 15:32:37160 const binding = Persistence.persistence.binding(uiSourceCode);
Tim van der Lippe1d6e57a2019-09-30 11:55:34161 if (binding && binding.network === uiSourceCode) {
Blink Reformat4c46d092018-04-07 15:32:37162 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34163 }
164 if (dirtyOnly && !uiSourceCode.isDirty()) {
Blink Reformat4c46d092018-04-07 15:32:37165 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34166 }
167 if (searchConfig.filePathMatchesFileQuery(uiSourceCode.fullDisplayName())) {
Blink Reformat4c46d092018-04-07 15:32:37168 result.push(uiSourceCode.url());
Tim van der Lippe1d6e57a2019-09-30 11:55:34169 }
Blink Reformat4c46d092018-04-07 15:32:37170 }
171 result.sort(String.naturalOrderComparator);
172 return result;
173 }
174
175 /**
176 * @param {number} searchId
177 * @param {!Workspace.Project} project
178 * @param {!Workspace.ProjectSearchConfig} searchConfig
179 * @param {!Array<string>} filesMathingFileQuery
180 * @param {!Array<string>} files
181 */
182 _processMatchingFilesForProject(searchId, project, searchConfig, filesMathingFileQuery, files) {
183 if (searchId !== this._searchId) {
184 this._searchFinishedCallback(false);
185 return;
186 }
187
188 files.sort(String.naturalOrderComparator);
189 files = files.intersectOrdered(filesMathingFileQuery, String.naturalOrderComparator);
190 const dirtyFiles = this._projectFilesMatchingFileQuery(project, searchConfig, true);
191 files = files.mergeOrdered(dirtyFiles, String.naturalOrderComparator);
192
193 const uiSourceCodes = [];
194 for (const file of files) {
195 const uiSourceCode = project.uiSourceCodeForURL(file);
Tim van der Lippe1d6e57a2019-09-30 11:55:34196 if (!uiSourceCode) {
Blink Reformat4c46d092018-04-07 15:32:37197 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34198 }
Blink Reformat4c46d092018-04-07 15:32:37199 const script = Bindings.DefaultScriptMapping.scriptForUISourceCode(uiSourceCode);
Tim van der Lippe1d6e57a2019-09-30 11:55:34200 if (script && !script.isAnonymousScript()) {
Blink Reformat4c46d092018-04-07 15:32:37201 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34202 }
Blink Reformat4c46d092018-04-07 15:32:37203 uiSourceCodes.push(uiSourceCode);
204 }
Tim van der Lippe8987f8f2020-01-03 15:03:16205 uiSourceCodes.sort(SourcesSearchScope._filesComparator);
Blink Reformat4c46d092018-04-07 15:32:37206 this._searchResultCandidates =
Tim van der Lippe8987f8f2020-01-03 15:03:16207 this._searchResultCandidates.mergeOrdered(uiSourceCodes, SourcesSearchScope._filesComparator);
Blink Reformat4c46d092018-04-07 15:32:37208 }
209
210 /**
211 * @param {number} searchId
212 * @param {!Common.Progress} progress
213 * @param {function()} callback
214 */
215 _processMatchingFiles(searchId, progress, callback) {
216 if (searchId !== this._searchId) {
217 this._searchFinishedCallback(false);
218 return;
219 }
220
221 const files = this._searchResultCandidates;
222 if (!files.length) {
223 progress.done();
224 callback();
225 return;
226 }
227
228 progress.setTotalWork(files.length);
229
230 let fileIndex = 0;
231 const maxFileContentRequests = 20;
232 let callbacksLeft = 0;
233
Tim van der Lippe1d6e57a2019-09-30 11:55:34234 for (let i = 0; i < maxFileContentRequests && i < files.length; ++i) {
Blink Reformat4c46d092018-04-07 15:32:37235 scheduleSearchInNextFileOrFinish.call(this);
Tim van der Lippe1d6e57a2019-09-30 11:55:34236 }
Blink Reformat4c46d092018-04-07 15:32:37237
238 /**
239 * @param {!Workspace.UISourceCode} uiSourceCode
Tim van der Lippe8987f8f2020-01-03 15:03:16240 * @this {SourcesSearchScope}
Blink Reformat4c46d092018-04-07 15:32:37241 */
242 function searchInNextFile(uiSourceCode) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34243 if (uiSourceCode.isDirty()) {
Blink Reformat4c46d092018-04-07 15:32:37244 contentLoaded.call(this, uiSourceCode, uiSourceCode.workingCopy());
Tim van der Lippe1d6e57a2019-09-30 11:55:34245 } else {
Rob Paveza2eb8c142019-10-13 18:02:38246 uiSourceCode.requestContent().then(deferredContent => {
247 contentLoaded.call(this, uiSourceCode, deferredContent.content || '');
248 });
Tim van der Lippe1d6e57a2019-09-30 11:55:34249 }
Blink Reformat4c46d092018-04-07 15:32:37250 }
251
252 /**
Tim van der Lippe8987f8f2020-01-03 15:03:16253 * @this {SourcesSearchScope}
Blink Reformat4c46d092018-04-07 15:32:37254 */
255 function scheduleSearchInNextFileOrFinish() {
256 if (fileIndex >= files.length) {
257 if (!callbacksLeft) {
258 progress.done();
259 callback();
260 return;
261 }
262 return;
263 }
264
265 ++callbacksLeft;
266 const uiSourceCode = files[fileIndex++];
267 setTimeout(searchInNextFile.bind(this, uiSourceCode), 0);
268 }
269
270 /**
271 * @param {!Workspace.UISourceCode} uiSourceCode
Rob Paveza2eb8c142019-10-13 18:02:38272 * @param {string} content
Tim van der Lippe8987f8f2020-01-03 15:03:16273 * @this {SourcesSearchScope}
Blink Reformat4c46d092018-04-07 15:32:37274 */
275 function contentLoaded(uiSourceCode, content) {
276 /**
277 * @param {!Common.ContentProvider.SearchMatch} a
278 * @param {!Common.ContentProvider.SearchMatch} b
279 */
280 function matchesComparator(a, b) {
281 return a.lineNumber - b.lineNumber;
282 }
283
284 progress.worked(1);
285 let matches = [];
286 const queries = this._searchConfig.queries();
287 if (content !== null) {
288 for (let i = 0; i < queries.length; ++i) {
289 const nextMatches = Common.ContentProvider.performSearchInContent(
290 content, queries[i], !this._searchConfig.ignoreCase(), this._searchConfig.isRegex());
291 matches = matches.mergeOrdered(nextMatches, matchesComparator);
292 }
293 }
294 if (matches) {
Tim van der Lippe8987f8f2020-01-03 15:03:16295 const searchResult = new FileBasedSearchResult(uiSourceCode, matches);
Blink Reformat4c46d092018-04-07 15:32:37296 this._searchResultCallback(searchResult);
297 }
298
299 --callbacksLeft;
300 scheduleSearchInNextFileOrFinish.call(this);
301 }
302 }
303
304 /**
305 * @override
306 */
307 stopSearch() {
308 ++this._searchId;
309 }
Tim van der Lippe8987f8f2020-01-03 15:03:16310}
Blink Reformat4c46d092018-04-07 15:32:37311
312/**
313 * @implements {Search.SearchResult}
314 */
Tim van der Lippe8987f8f2020-01-03 15:03:16315export class FileBasedSearchResult {
Blink Reformat4c46d092018-04-07 15:32:37316 /**
317 * @param {!Workspace.UISourceCode} uiSourceCode
318 * @param {!Array.<!Common.ContentProvider.SearchMatch>} searchMatches
319 */
320 constructor(uiSourceCode, searchMatches) {
321 this._uiSourceCode = uiSourceCode;
322 this._searchMatches = searchMatches;
323 }
324
325 /**
326 * @override
327 * @return {string}
328 */
329 label() {
330 return this._uiSourceCode.displayName();
331 }
332
333 /**
334 * @override
335 * @return {string}
336 */
337 description() {
338 return this._uiSourceCode.fullDisplayName();
339 }
340
341 /**
342 * @override
343 * @return {number}
344 */
345 matchesCount() {
346 return this._searchMatches.length;
347 }
348
349 /**
350 * @override
351 * @param {number} index
352 * @return {string}
353 */
354 matchLineContent(index) {
355 return this._searchMatches[index].lineContent;
356 }
357
358 /**
359 * @override
360 * @param {number} index
361 * @return {!Object}
362 */
363 matchRevealable(index) {
364 const match = this._searchMatches[index];
Tim van der Lippeffa78622019-09-16 12:07:12365 return this._uiSourceCode.uiLocation(match.lineNumber, undefined);
Blink Reformat4c46d092018-04-07 15:32:37366 }
367
368 /**
369 * @override
370 * @param {number} index
371 * @return {?}
372 */
373 matchLabel(index) {
374 return this._searchMatches[index].lineNumber + 1;
375 }
Tim van der Lippe8987f8f2020-01-03 15:03:16376}