Two things:

* Removed the `Directory` argument to `didSearchPaths`.
Now each searcher gets its own instance of `didSearchPaths` that is parameterized by provider.
* Simplified `DefaultDirectorySearcher.search()` so it creates one `DirectorySearch`
rather than one per `Directory` passed to `search()`.
This commit is contained in:
Michael Bolin
2015-06-03 23:29:56 -04:00
parent 18ac7d0cbc
commit 0630bce95c
3 changed files with 29 additions and 34 deletions

View File

@@ -952,7 +952,9 @@ describe "Workspace", ->
onFakeSearchCreated?(this)
then: (args...) ->
@promise.then.apply(@promise, args)
cancel: -> @cancelled = true
cancel: ->
@cancelled = true
@hoistedReject()
beforeEach ->
fakeSearch = null
@@ -978,8 +980,7 @@ describe "Workspace", ->
]
onFakeSearchCreated = (fakeSearch) ->
fakeSearch.options.didMatch(searchResult)
directory1 = atom.project.getDirectories()[atom.project.getPaths().indexOf(dir1)]
fakeSearch.options.didSearchPaths(directory1, numPathsToPretendToSearchInCustomDirectorySearcher)
fakeSearch.options.didSearchPaths(numPathsToPretendToSearchInCustomDirectorySearcher)
fakeSearch.hoistedResolve()
resultPaths = []

View File

@@ -4,7 +4,7 @@ Task = require './task'
#
# Implements thenable so it can be used with `Promise.all()`.
class DirectorySearch
constructor: (directory, regex, options) ->
constructor: (rootPaths, regex, options) ->
scanHandlerOptions =
ignoreCase: regex.ignoreCase
inclusions: options.inclusions
@@ -15,10 +15,10 @@ class DirectorySearch
@task = new Task(require.resolve('./scan-handler'))
@task.on 'scan:result-found', options.didMatch
@task.on 'scan:file-error', options.didError
@task.on 'scan:paths-searched', (count) -> options.didSearchPaths(directory, count)
@task.on 'scan:paths-searched', options.didSearchPaths
@promise = new Promise (resolve, reject) =>
@task.on('task:cancelled', reject)
@task.start([directory.getPath()], regex.source, scanHandlerOptions, resolve)
@task.start(rootPaths, regex.source, scanHandlerOptions, resolve)
# Public: Implementation of `then()` to satisfy the *thenable* contract.
# This makes it possible to use a `DirectorySearch` with `Promise.all()`.
@@ -64,7 +64,6 @@ class DefaultDirectorySearcher
# * `range` {Range} Identifies the matching region in the file. (Likely as an array of numeric arrays.)
# * `didError` {Function} call with an Error if there is a problem during the search.
# * `didSearchPaths` {Function} periodically call with the number of paths searched thus far.
# This takes two arguments: the `Directory` and the count.
# * `inclusions` {Array} of glob patterns (as strings) to search within. Note that this
# array may be empty, indicating that all files should be searched.
#
@@ -79,21 +78,18 @@ class DefaultDirectorySearcher
# Returns a *thenable* `DirectorySearch` that includes a `cancel()` method. If `cancel()` is
# invoked before the `DirectorySearch` is determined, it will reject the `DirectorySearch`.
search: (directories, regex, options) ->
# Make a mutable copy of the directories array.
directories = directories.slice(0)
rootPaths = directories.map (directory) -> directory.getPath()
isCancelled = false
directorySearch = new DirectorySearch(rootPaths, regex, options)
promise = new Promise (resolve, reject) ->
run = ->
directorySearch.then resolve, ->
if isCancelled
reject()
else if directories.length
directory = directories.shift()
thenable = new DirectorySearch(directory, regex, options)
thenable.then(run, reject)
else
resolve()
run()
else
reject()
return {
then: promise.then.bind(promise)
cancel: -> isCancelled = true
cancel: ->
isCancelled = true
directorySearch.cancel()
}

View File

@@ -831,32 +831,30 @@ class Workspace extends Model
onPathsSearchedOption = options.onPathsSearched
totalNumberOfPathsSearched = 0
numberOfPathsSearchedForDirectory = new Map()
onPathsSearched = (directory, numberOfPathsSearched) ->
oldValue = numberOfPathsSearchedForDirectory.get(directory)
onPathsSearched = (searcher, numberOfPathsSearched) ->
oldValue = numberOfPathsSearchedForDirectory.get(searcher)
if oldValue
totalNumberOfPathsSearched -= oldValue
numberOfPathsSearchedForDirectory.set(directory, numberOfPathsSearched)
numberOfPathsSearchedForDirectory.set(searcher, numberOfPathsSearched)
totalNumberOfPathsSearched += numberOfPathsSearched
onPathsSearchedOption(totalNumberOfPathsSearched)
else
onPathsSearched = ->
# Build up the options object that will be shared by all searchers.
searchOptions =
inclusions: options.paths or []
includeHidden: true
excludeVcsIgnores: atom.config.get('core.excludeVcsIgnoredPaths')
exclusions: atom.config.get('core.ignoredNames')
follow: atom.config.get('core.followSymlinks')
didMatch: (result) ->
iterator(result) unless atom.project.isPathModified(result.filePath)
didError: (error) ->
iterator(null, error)
didSearchPaths: onPathsSearched
# Kick off all of the searches and unify them into one Promise.
allSearches = []
directoriesForSearcher.forEach (directories, searcher) ->
searchOptions =
inclusions: options.paths or []
includeHidden: true
excludeVcsIgnores: atom.config.get('core.excludeVcsIgnoredPaths')
exclusions: atom.config.get('core.ignoredNames')
follow: atom.config.get('core.followSymlinks')
didMatch: (result) ->
iterator(result) unless atom.project.isPathModified(result.filePath)
didError: (error) ->
iterator(null, error)
didSearchPaths: (count) -> onPathsSearched(searcher, count)
directorySearcher = searcher.search(directories, regex, searchOptions)
allSearches.push(directorySearcher)
searchPromise = Promise.all(allSearches)