| 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 |