OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * | 10 * |
11 * 2. Redistributions in binary form must reproduce the above | 11 * 2. Redistributions in binary form must reproduce the above |
12 * copyright notice, this list of conditions and the following disclaimer | 12 * copyright notice, this list of conditions and the following disclaimer |
13 * in the documentation and/or other materials provided with the | 13 * in the documentation and/or other materials provided with the |
14 * distribution. | 14 * distribution. |
15 * | 15 * |
16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS | 16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS |
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. | 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. |
20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 */ | 27 */ |
28 | |
29 /** | 28 /** |
30 * @constructor | |
31 * @implements {WebInspector.SearchScope} | 29 * @implements {WebInspector.SearchScope} |
| 30 * @unrestricted |
32 */ | 31 */ |
33 WebInspector.SourcesSearchScope = function() | 32 WebInspector.SourcesSearchScope = class { |
34 { | 33 constructor() { |
35 // FIXME: Add title once it is used by search controller. | 34 // FIXME: Add title once it is used by search controller. |
36 this._searchId = 0; | 35 this._searchId = 0; |
37 }; | 36 } |
38 | 37 |
39 /** | 38 /** |
40 * @param {!WebInspector.UISourceCode} uiSourceCode1 | 39 * @param {!WebInspector.UISourceCode} uiSourceCode1 |
41 * @param {!WebInspector.UISourceCode} uiSourceCode2 | 40 * @param {!WebInspector.UISourceCode} uiSourceCode2 |
42 * @return {number} | 41 * @return {number} |
43 */ | 42 */ |
44 WebInspector.SourcesSearchScope._filesComparator = function(uiSourceCode1, uiSou
rceCode2) | 43 static _filesComparator(uiSourceCode1, uiSourceCode2) { |
45 { | |
46 if (uiSourceCode1.isDirty() && !uiSourceCode2.isDirty()) | 44 if (uiSourceCode1.isDirty() && !uiSourceCode2.isDirty()) |
47 return -1; | 45 return -1; |
48 if (!uiSourceCode1.isDirty() && uiSourceCode2.isDirty()) | 46 if (!uiSourceCode1.isDirty() && uiSourceCode2.isDirty()) |
49 return 1; | 47 return 1; |
50 var url1 = uiSourceCode1.url(); | 48 var url1 = uiSourceCode1.url(); |
51 var url2 = uiSourceCode2.url(); | 49 var url2 = uiSourceCode2.url(); |
52 if (url1 && !url2) | 50 if (url1 && !url2) |
53 return -1; | 51 return -1; |
54 if (!url1 && url2) | 52 if (!url1 && url2) |
55 return 1; | 53 return 1; |
56 return String.naturalOrderComparator(uiSourceCode1.fullDisplayName(), uiSour
ceCode2.fullDisplayName()); | 54 return String.naturalOrderComparator(uiSourceCode1.fullDisplayName(), uiSour
ceCode2.fullDisplayName()); |
| 55 } |
| 56 |
| 57 /** |
| 58 * @override |
| 59 * @param {!WebInspector.Progress} progress |
| 60 */ |
| 61 performIndexing(progress) { |
| 62 this.stopSearch(); |
| 63 |
| 64 var projects = this._projects(); |
| 65 var compositeProgress = new WebInspector.CompositeProgress(progress); |
| 66 for (var i = 0; i < projects.length; ++i) { |
| 67 var project = projects[i]; |
| 68 var projectProgress = compositeProgress.createSubProgress(project.uiSource
Codes().length); |
| 69 project.indexContent(projectProgress); |
| 70 } |
| 71 } |
| 72 |
| 73 /** |
| 74 * @return {!Array.<!WebInspector.Project>} |
| 75 */ |
| 76 _projects() { |
| 77 /** |
| 78 * @param {!WebInspector.Project} project |
| 79 * @return {boolean} |
| 80 */ |
| 81 function filterOutServiceProjects(project) { |
| 82 return project.type() !== WebInspector.projectTypes.Service; |
| 83 } |
| 84 |
| 85 /** |
| 86 * @param {!WebInspector.Project} project |
| 87 * @return {boolean} |
| 88 */ |
| 89 function filterOutContentScriptsIfNeeded(project) { |
| 90 return WebInspector.moduleSetting('searchInContentScripts').get() || |
| 91 project.type() !== WebInspector.projectTypes.ContentScripts; |
| 92 } |
| 93 |
| 94 return WebInspector.workspace.projects().filter(filterOutServiceProjects).fi
lter(filterOutContentScriptsIfNeeded); |
| 95 } |
| 96 |
| 97 /** |
| 98 * @override |
| 99 * @param {!WebInspector.ProjectSearchConfig} searchConfig |
| 100 * @param {!WebInspector.Progress} progress |
| 101 * @param {function(!WebInspector.FileBasedSearchResult)} searchResultCallback |
| 102 * @param {function(boolean)} searchFinishedCallback |
| 103 */ |
| 104 performSearch(searchConfig, progress, searchResultCallback, searchFinishedCall
back) { |
| 105 this.stopSearch(); |
| 106 this._searchResultCandidates = []; |
| 107 this._searchResultCallback = searchResultCallback; |
| 108 this._searchFinishedCallback = searchFinishedCallback; |
| 109 this._searchConfig = searchConfig; |
| 110 |
| 111 var projects = this._projects(); |
| 112 var barrier = new CallbackBarrier(); |
| 113 var compositeProgress = new WebInspector.CompositeProgress(progress); |
| 114 var searchContentProgress = compositeProgress.createSubProgress(); |
| 115 var findMatchingFilesProgress = new WebInspector.CompositeProgress(composite
Progress.createSubProgress()); |
| 116 for (var i = 0; i < projects.length; ++i) { |
| 117 var project = projects[i]; |
| 118 var weight = project.uiSourceCodes().length; |
| 119 var findMatchingFilesInProjectProgress = findMatchingFilesProgress.createS
ubProgress(weight); |
| 120 var barrierCallback = barrier.createCallback(); |
| 121 var filesMathingFileQuery = this._projectFilesMatchingFileQuery(project, s
earchConfig); |
| 122 var callback = this._processMatchingFilesForProject.bind( |
| 123 this, this._searchId, project, filesMathingFileQuery, barrierCallback)
; |
| 124 project.findFilesMatchingSearchRequest( |
| 125 searchConfig, filesMathingFileQuery, findMatchingFilesInProjectProgres
s, callback); |
| 126 } |
| 127 barrier.callWhenDone(this._processMatchingFiles.bind( |
| 128 this, this._searchId, searchContentProgress, this._searchFinishedCallbac
k.bind(this, true))); |
| 129 } |
| 130 |
| 131 /** |
| 132 * @param {!WebInspector.Project} project |
| 133 * @param {!WebInspector.ProjectSearchConfig} searchConfig |
| 134 * @param {boolean=} dirtyOnly |
| 135 * @return {!Array.<string>} |
| 136 */ |
| 137 _projectFilesMatchingFileQuery(project, searchConfig, dirtyOnly) { |
| 138 var result = []; |
| 139 var uiSourceCodes = project.uiSourceCodes(); |
| 140 for (var i = 0; i < uiSourceCodes.length; ++i) { |
| 141 var uiSourceCode = uiSourceCodes[i]; |
| 142 var binding = WebInspector.persistence.binding(uiSourceCode); |
| 143 if (binding && binding.fileSystem === uiSourceCode) |
| 144 continue; |
| 145 if (dirtyOnly && !uiSourceCode.isDirty()) |
| 146 continue; |
| 147 if (this._searchConfig.filePathMatchesFileQuery(uiSourceCode.fullDisplayNa
me())) |
| 148 result.push(uiSourceCode.url()); |
| 149 } |
| 150 result.sort(String.naturalOrderComparator); |
| 151 return result; |
| 152 } |
| 153 |
| 154 /** |
| 155 * @param {number} searchId |
| 156 * @param {!WebInspector.Project} project |
| 157 * @param {!Array.<string>} filesMathingFileQuery |
| 158 * @param {function()} callback |
| 159 * @param {!Array.<string>} files |
| 160 */ |
| 161 _processMatchingFilesForProject(searchId, project, filesMathingFileQuery, call
back, files) { |
| 162 if (searchId !== this._searchId) { |
| 163 this._searchFinishedCallback(false); |
| 164 return; |
| 165 } |
| 166 |
| 167 files.sort(String.naturalOrderComparator); |
| 168 files = files.intersectOrdered(filesMathingFileQuery, String.naturalOrderCom
parator); |
| 169 var dirtyFiles = this._projectFilesMatchingFileQuery(project, this._searchCo
nfig, true); |
| 170 files = files.mergeOrdered(dirtyFiles, String.naturalOrderComparator); |
| 171 |
| 172 var uiSourceCodes = []; |
| 173 for (var i = 0; i < files.length; ++i) { |
| 174 var uiSourceCode = project.uiSourceCodeForURL(files[i]); |
| 175 if (uiSourceCode) { |
| 176 var script = WebInspector.DefaultScriptMapping.scriptForUISourceCode(uiS
ourceCode); |
| 177 if (script && !script.isAnonymousScript()) |
| 178 continue; |
| 179 uiSourceCodes.push(uiSourceCode); |
| 180 } |
| 181 } |
| 182 uiSourceCodes.sort(WebInspector.SourcesSearchScope._filesComparator); |
| 183 this._searchResultCandidates = |
| 184 this._searchResultCandidates.mergeOrdered(uiSourceCodes, WebInspector.So
urcesSearchScope._filesComparator); |
| 185 callback(); |
| 186 } |
| 187 |
| 188 /** |
| 189 * @param {number} searchId |
| 190 * @param {!WebInspector.Progress} progress |
| 191 * @param {function()} callback |
| 192 */ |
| 193 _processMatchingFiles(searchId, progress, callback) { |
| 194 if (searchId !== this._searchId) { |
| 195 this._searchFinishedCallback(false); |
| 196 return; |
| 197 } |
| 198 |
| 199 var files = this._searchResultCandidates; |
| 200 if (!files.length) { |
| 201 progress.done(); |
| 202 callback(); |
| 203 return; |
| 204 } |
| 205 |
| 206 progress.setTotalWork(files.length); |
| 207 |
| 208 var fileIndex = 0; |
| 209 var maxFileContentRequests = 20; |
| 210 var callbacksLeft = 0; |
| 211 |
| 212 for (var i = 0; i < maxFileContentRequests && i < files.length; ++i) |
| 213 scheduleSearchInNextFileOrFinish.call(this); |
| 214 |
| 215 /** |
| 216 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 217 * @this {WebInspector.SourcesSearchScope} |
| 218 */ |
| 219 function searchInNextFile(uiSourceCode) { |
| 220 if (uiSourceCode.isDirty()) |
| 221 contentLoaded.call(this, uiSourceCode, uiSourceCode.workingCopy()); |
| 222 else |
| 223 uiSourceCode.checkContentUpdated(true, contentUpdated.bind(this, uiSourc
eCode)); |
| 224 } |
| 225 |
| 226 /** |
| 227 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 228 * @this {WebInspector.SourcesSearchScope} |
| 229 */ |
| 230 function contentUpdated(uiSourceCode) { |
| 231 uiSourceCode.requestContent().then(contentLoaded.bind(this, uiSourceCode))
; |
| 232 } |
| 233 |
| 234 /** |
| 235 * @this {WebInspector.SourcesSearchScope} |
| 236 */ |
| 237 function scheduleSearchInNextFileOrFinish() { |
| 238 if (fileIndex >= files.length) { |
| 239 if (!callbacksLeft) { |
| 240 progress.done(); |
| 241 callback(); |
| 242 return; |
| 243 } |
| 244 return; |
| 245 } |
| 246 |
| 247 ++callbacksLeft; |
| 248 var uiSourceCode = files[fileIndex++]; |
| 249 setTimeout(searchInNextFile.bind(this, uiSourceCode), 0); |
| 250 } |
| 251 |
| 252 /** |
| 253 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 254 * @param {?string} content |
| 255 * @this {WebInspector.SourcesSearchScope} |
| 256 */ |
| 257 function contentLoaded(uiSourceCode, content) { |
| 258 /** |
| 259 * @param {!WebInspector.ContentProvider.SearchMatch} a |
| 260 * @param {!WebInspector.ContentProvider.SearchMatch} b |
| 261 */ |
| 262 function matchesComparator(a, b) { |
| 263 return a.lineNumber - b.lineNumber; |
| 264 } |
| 265 |
| 266 progress.worked(1); |
| 267 var matches = []; |
| 268 var queries = this._searchConfig.queries(); |
| 269 if (content !== null) { |
| 270 for (var i = 0; i < queries.length; ++i) { |
| 271 var nextMatches = WebInspector.ContentProvider.performSearchInContent( |
| 272 content, queries[i], !this._searchConfig.ignoreCase(), this._searc
hConfig.isRegex()); |
| 273 matches = matches.mergeOrdered(nextMatches, matchesComparator); |
| 274 } |
| 275 } |
| 276 if (matches) { |
| 277 var searchResult = new WebInspector.FileBasedSearchResult(uiSourceCode,
matches); |
| 278 this._searchResultCallback(searchResult); |
| 279 } |
| 280 |
| 281 --callbacksLeft; |
| 282 scheduleSearchInNextFileOrFinish.call(this); |
| 283 } |
| 284 } |
| 285 |
| 286 /** |
| 287 * @override |
| 288 */ |
| 289 stopSearch() { |
| 290 ++this._searchId; |
| 291 } |
| 292 |
| 293 /** |
| 294 * @override |
| 295 * @param {!WebInspector.ProjectSearchConfig} searchConfig |
| 296 * @return {!WebInspector.FileBasedSearchResultsPane} |
| 297 */ |
| 298 createSearchResultsPane(searchConfig) { |
| 299 return new WebInspector.FileBasedSearchResultsPane(searchConfig); |
| 300 } |
57 }; | 301 }; |
58 | 302 |
59 | 303 |
60 WebInspector.SourcesSearchScope.prototype = { | |
61 /** | |
62 * @override | |
63 * @param {!WebInspector.Progress} progress | |
64 */ | |
65 performIndexing: function(progress) | |
66 { | |
67 this.stopSearch(); | |
68 | |
69 var projects = this._projects(); | |
70 var compositeProgress = new WebInspector.CompositeProgress(progress); | |
71 for (var i = 0; i < projects.length; ++i) { | |
72 var project = projects[i]; | |
73 var projectProgress = compositeProgress.createSubProgress(project.ui
SourceCodes().length); | |
74 project.indexContent(projectProgress); | |
75 } | |
76 }, | |
77 | |
78 /** | |
79 * @return {!Array.<!WebInspector.Project>} | |
80 */ | |
81 _projects: function() | |
82 { | |
83 /** | |
84 * @param {!WebInspector.Project} project | |
85 * @return {boolean} | |
86 */ | |
87 function filterOutServiceProjects(project) | |
88 { | |
89 return project.type() !== WebInspector.projectTypes.Service; | |
90 } | |
91 | |
92 /** | |
93 * @param {!WebInspector.Project} project | |
94 * @return {boolean} | |
95 */ | |
96 function filterOutContentScriptsIfNeeded(project) | |
97 { | |
98 return WebInspector.moduleSetting("searchInContentScripts").get() ||
project.type() !== WebInspector.projectTypes.ContentScripts; | |
99 } | |
100 | |
101 return WebInspector.workspace.projects().filter(filterOutServiceProjects
).filter(filterOutContentScriptsIfNeeded); | |
102 }, | |
103 | |
104 /** | |
105 * @override | |
106 * @param {!WebInspector.ProjectSearchConfig} searchConfig | |
107 * @param {!WebInspector.Progress} progress | |
108 * @param {function(!WebInspector.FileBasedSearchResult)} searchResultCallba
ck | |
109 * @param {function(boolean)} searchFinishedCallback | |
110 */ | |
111 performSearch: function(searchConfig, progress, searchResultCallback, search
FinishedCallback) | |
112 { | |
113 this.stopSearch(); | |
114 this._searchResultCandidates = []; | |
115 this._searchResultCallback = searchResultCallback; | |
116 this._searchFinishedCallback = searchFinishedCallback; | |
117 this._searchConfig = searchConfig; | |
118 | |
119 var projects = this._projects(); | |
120 var barrier = new CallbackBarrier(); | |
121 var compositeProgress = new WebInspector.CompositeProgress(progress); | |
122 var searchContentProgress = compositeProgress.createSubProgress(); | |
123 var findMatchingFilesProgress = new WebInspector.CompositeProgress(compo
siteProgress.createSubProgress()); | |
124 for (var i = 0; i < projects.length; ++i) { | |
125 var project = projects[i]; | |
126 var weight = project.uiSourceCodes().length; | |
127 var findMatchingFilesInProjectProgress = findMatchingFilesProgress.c
reateSubProgress(weight); | |
128 var barrierCallback = barrier.createCallback(); | |
129 var filesMathingFileQuery = this._projectFilesMatchingFileQuery(proj
ect, searchConfig); | |
130 var callback = this._processMatchingFilesForProject.bind(this, this.
_searchId, project, filesMathingFileQuery, barrierCallback); | |
131 project.findFilesMatchingSearchRequest(searchConfig, filesMathingFil
eQuery, findMatchingFilesInProjectProgress, callback); | |
132 } | |
133 barrier.callWhenDone(this._processMatchingFiles.bind(this, this._searchI
d, searchContentProgress, this._searchFinishedCallback.bind(this, true))); | |
134 }, | |
135 | |
136 /** | |
137 * @param {!WebInspector.Project} project | |
138 * @param {!WebInspector.ProjectSearchConfig} searchConfig | |
139 * @param {boolean=} dirtyOnly | |
140 * @return {!Array.<string>} | |
141 */ | |
142 _projectFilesMatchingFileQuery: function(project, searchConfig, dirtyOnly) | |
143 { | |
144 var result = []; | |
145 var uiSourceCodes = project.uiSourceCodes(); | |
146 for (var i = 0; i < uiSourceCodes.length; ++i) { | |
147 var uiSourceCode = uiSourceCodes[i]; | |
148 var binding = WebInspector.persistence.binding(uiSourceCode); | |
149 if (binding && binding.fileSystem === uiSourceCode) | |
150 continue; | |
151 if (dirtyOnly && !uiSourceCode.isDirty()) | |
152 continue; | |
153 if (this._searchConfig.filePathMatchesFileQuery(uiSourceCode.fullDis
playName())) | |
154 result.push(uiSourceCode.url()); | |
155 } | |
156 result.sort(String.naturalOrderComparator); | |
157 return result; | |
158 }, | |
159 | |
160 /** | |
161 * @param {number} searchId | |
162 * @param {!WebInspector.Project} project | |
163 * @param {!Array.<string>} filesMathingFileQuery | |
164 * @param {function()} callback | |
165 * @param {!Array.<string>} files | |
166 */ | |
167 _processMatchingFilesForProject: function(searchId, project, filesMathingFil
eQuery, callback, files) | |
168 { | |
169 if (searchId !== this._searchId) { | |
170 this._searchFinishedCallback(false); | |
171 return; | |
172 } | |
173 | |
174 files.sort(String.naturalOrderComparator); | |
175 files = files.intersectOrdered(filesMathingFileQuery, String.naturalOrde
rComparator); | |
176 var dirtyFiles = this._projectFilesMatchingFileQuery(project, this._sear
chConfig, true); | |
177 files = files.mergeOrdered(dirtyFiles, String.naturalOrderComparator); | |
178 | |
179 var uiSourceCodes = []; | |
180 for (var i = 0; i < files.length; ++i) { | |
181 var uiSourceCode = project.uiSourceCodeForURL(files[i]); | |
182 if (uiSourceCode) { | |
183 var script = WebInspector.DefaultScriptMapping.scriptForUISource
Code(uiSourceCode); | |
184 if (script && !script.isAnonymousScript()) | |
185 continue; | |
186 uiSourceCodes.push(uiSourceCode); | |
187 } | |
188 } | |
189 uiSourceCodes.sort(WebInspector.SourcesSearchScope._filesComparator); | |
190 this._searchResultCandidates = this._searchResultCandidates.mergeOrdered
(uiSourceCodes, WebInspector.SourcesSearchScope._filesComparator); | |
191 callback(); | |
192 }, | |
193 | |
194 /** | |
195 * @param {number} searchId | |
196 * @param {!WebInspector.Progress} progress | |
197 * @param {function()} callback | |
198 */ | |
199 _processMatchingFiles: function(searchId, progress, callback) | |
200 { | |
201 if (searchId !== this._searchId) { | |
202 this._searchFinishedCallback(false); | |
203 return; | |
204 } | |
205 | |
206 var files = this._searchResultCandidates; | |
207 if (!files.length) { | |
208 progress.done(); | |
209 callback(); | |
210 return; | |
211 } | |
212 | |
213 progress.setTotalWork(files.length); | |
214 | |
215 var fileIndex = 0; | |
216 var maxFileContentRequests = 20; | |
217 var callbacksLeft = 0; | |
218 | |
219 for (var i = 0; i < maxFileContentRequests && i < files.length; ++i) | |
220 scheduleSearchInNextFileOrFinish.call(this); | |
221 | |
222 /** | |
223 * @param {!WebInspector.UISourceCode} uiSourceCode | |
224 * @this {WebInspector.SourcesSearchScope} | |
225 */ | |
226 function searchInNextFile(uiSourceCode) | |
227 { | |
228 if (uiSourceCode.isDirty()) | |
229 contentLoaded.call(this, uiSourceCode, uiSourceCode.workingCopy(
)); | |
230 else | |
231 uiSourceCode.checkContentUpdated(true, contentUpdated.bind(this,
uiSourceCode)); | |
232 } | |
233 | |
234 /** | |
235 * @param {!WebInspector.UISourceCode} uiSourceCode | |
236 * @this {WebInspector.SourcesSearchScope} | |
237 */ | |
238 function contentUpdated(uiSourceCode) | |
239 { | |
240 uiSourceCode.requestContent().then(contentLoaded.bind(this, uiSource
Code)); | |
241 } | |
242 | |
243 /** | |
244 * @this {WebInspector.SourcesSearchScope} | |
245 */ | |
246 function scheduleSearchInNextFileOrFinish() | |
247 { | |
248 if (fileIndex >= files.length) { | |
249 if (!callbacksLeft) { | |
250 progress.done(); | |
251 callback(); | |
252 return; | |
253 } | |
254 return; | |
255 } | |
256 | |
257 ++callbacksLeft; | |
258 var uiSourceCode = files[fileIndex++]; | |
259 setTimeout(searchInNextFile.bind(this, uiSourceCode), 0); | |
260 } | |
261 | |
262 /** | |
263 * @param {!WebInspector.UISourceCode} uiSourceCode | |
264 * @param {?string} content | |
265 * @this {WebInspector.SourcesSearchScope} | |
266 */ | |
267 function contentLoaded(uiSourceCode, content) | |
268 { | |
269 /** | |
270 * @param {!WebInspector.ContentProvider.SearchMatch} a | |
271 * @param {!WebInspector.ContentProvider.SearchMatch} b | |
272 */ | |
273 function matchesComparator(a, b) | |
274 { | |
275 return a.lineNumber - b.lineNumber; | |
276 } | |
277 | |
278 progress.worked(1); | |
279 var matches = []; | |
280 var queries = this._searchConfig.queries(); | |
281 if (content !== null) { | |
282 for (var i = 0; i < queries.length; ++i) { | |
283 var nextMatches = WebInspector.ContentProvider.performSearch
InContent(content, queries[i], !this._searchConfig.ignoreCase(), this._searchCon
fig.isRegex()); | |
284 matches = matches.mergeOrdered(nextMatches, matchesComparato
r); | |
285 } | |
286 } | |
287 if (matches) { | |
288 var searchResult = new WebInspector.FileBasedSearchResult(uiSour
ceCode, matches); | |
289 this._searchResultCallback(searchResult); | |
290 } | |
291 | |
292 --callbacksLeft; | |
293 scheduleSearchInNextFileOrFinish.call(this); | |
294 } | |
295 }, | |
296 | |
297 /** | |
298 * @override | |
299 */ | |
300 stopSearch: function() | |
301 { | |
302 ++this._searchId; | |
303 }, | |
304 | |
305 /** | |
306 * @override | |
307 * @param {!WebInspector.ProjectSearchConfig} searchConfig | |
308 * @return {!WebInspector.FileBasedSearchResultsPane} | |
309 */ | |
310 createSearchResultsPane: function(searchConfig) | |
311 { | |
312 return new WebInspector.FileBasedSearchResultsPane(searchConfig); | |
313 } | |
314 }; | |
OLD | NEW |