Changed the contract of DefaultDirectorySearcher in two significant ways:

* `search()` takes an array of `Directory` objects rather than an individual object.
* `options.didSearchPaths` now takes the `Directory` in addition to the `count` as an argument.
This commit is contained in:
Michael Bolin
2015-06-03 22:20:39 -04:00
parent 36123faf5d
commit 7dc3d07f8a
3 changed files with 34 additions and 27 deletions

View File

@@ -978,7 +978,8 @@ describe "Workspace", ->
]
onFakeSearchCreated = (fakeSearch) ->
fakeSearch.options.didMatch(searchResult)
fakeSearch.options.didSearchPaths(numPathsToPretendToSearchInCustomDirectorySearcher)
directory1 = atom.project.getDirectories()[atom.project.getPaths().indexOf(dir1)]
fakeSearch.options.didSearchPaths(directory1, numPathsToPretendToSearchInCustomDirectorySearcher)
fakeSearch.hoistedResolve()
resultPaths = []

View File

@@ -4,9 +4,7 @@ Task = require './task'
#
# Implements thenable so it can be used with `Promise.all()`.
class DirectorySearch
# Public: Creates a new DirectorySearch that will not start running until the
# `emitter` that is private to this file emits an event with the specified `id`.
constructor: (rootPath, regex, options) ->
constructor: (directory, regex, options) ->
scanHandlerOptions =
ignoreCase: regex.ignoreCase
inclusions: options.inclusions
@@ -17,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', options.didSearchPaths
@task.on 'scan:paths-searched', (count) -> options.didSearchPaths(directory, count)
@promise = new Promise (resolve, reject) =>
@task.on('task:cancelled', reject)
@task.start([rootPath], regex.source, scanHandlerOptions, resolve)
@task.start([directory.getPath()], regex.source, scanHandlerOptions, resolve)
# Public: Implementation of `then()` to satisfy the *thenable* contract.
# This makes it possible to use a `DirectorySearch` with `Promise.all()`.
@@ -66,6 +64,7 @@ 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.
#
@@ -80,15 +79,16 @@ 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) ->
rootPaths = directories.map (directory) -> directory.getPath()
# Make a mutable copy of the directories array.
directories = directories.slice(0)
isCancelled = false
promise = new Promise (resolve, reject) ->
run = ->
if isCancelled
reject()
else if rootPaths.length
rootPath = rootPaths.shift()
thenable = new DirectorySearch(rootPath, regex, options)
else if directories.length
directory = directories.shift()
thenable = new DirectorySearch(directory, regex, options)
thenable.then(run, reject)
else
resolve()

View File

@@ -811,15 +811,20 @@ class Workspace extends Model
iterator = options
options = {}
# Find a searcher for every Directory in the project.
searchersAndDirectories = []
# Find a searcher for every Directory in the project. Each searcher that is matched
# will be associated with an Array of Directory objects in the Map.
directoriesForSearcher = new Map()
for directory in atom.project.getDirectories()
searcher = @defaultDirectorySearcher
for directorySearcher in @directorySearchers
if directorySearcher.canSearchDirectory(directory)
searcher = directorySearcher
break
searchersAndDirectories.push({searcher, directory})
directories = directoriesForSearcher.get(searcher)
unless directories
directories = []
directoriesForSearcher.set(searcher, directories)
directories.push(directory)
# Define the onPathsSearched callback.
if _.isFunction(options.onPathsSearched)
@@ -838,22 +843,23 @@ class Workspace extends Model
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 = []
for entry in searchersAndDirectories
{searcher, directory} = entry
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.bind(undefined, directory)
directorySearcher = searcher.search([directory], regex, searchOptions)
directoriesForSearcher.forEach (directories, searcher) ->
directorySearcher = searcher.search(directories, regex, searchOptions)
allSearches.push(directorySearcher)
searchPromise = Promise.all(allSearches)