public bool UpdateDocumentHierarchy(IEnumerable<string> pathsToUpdate, FilesPatternProvider filesPatternProvider, BackgroundIndexer worker)
        {
            if (DocumentHierarchy == null)
            {
                return false;
            }
            var documentHierarchyIndexer = new DocumentHierarchyIndexer(DocumentHierarchy);
            bool changed = false;
            foreach (string path in pathsToUpdate)
            {
                INode node = DocumentHierarchy.GetNode(path);
                bool nodeShouldBeRemoved = node != null;
                var fileSystemEntryList = GetFileList(path, filesPatternProvider, worker);

                foreach (PowershellFileParser fileSystemEntry in fileSystemEntryList)
                {
                    // this is to prevent from reporting progress after deletion if the node is only updated
                    if (fileSystemEntry.Path == path && node != null)
                    {
                        DocumentHierarchy.RemoveNode(node);
                        nodeShouldBeRemoved = false;
                    }
                    documentHierarchyIndexer.AddFileSystemNode(fileSystemEntry);
                    changed = true;
                }
                if (nodeShouldBeRemoved)
                {
                    DocumentHierarchy.RemoveNode(node);
                    changed = true;
                    ReportProgress(worker, path);
                }
            }
            return changed;
        }
        // running in UI thread
        public void ReindexSearchTree(BackgroundIndexerParams indexerParams)
        {
            if (indexerParams.PathsChanged == null)
            {
                lock (BackgroundIndexers)
                {
                    foreach (var ind in BackgroundIndexers)
                    {
                        ind.CancelAsync();
                    }
                    BackgroundIndexers.Clear();
                }
            }

            var indexer = new BackgroundIndexer();
            indexer.RunWorkerCompleted += BackgroundIndexerWorkCompleted;
            indexer.ProgressChanged += BackgroundIndexerProgressChanged;
            indexer.RunWorkerAsync(indexerParams);
            lock (BackgroundIndexers)
            {
                BackgroundIndexers.Add(indexer);
            }
        }
 private void ReportProgress(BackgroundIndexer worker, string path)
 {
     if (worker.CancellationPending)
     {
         throw new OperationCanceledException();
     }
     worker.ReportProgressInCurrentThread(path);
 }
        private IEnumerable<PowershellFileParser> GetFileList(string path, FilesPatternProvider filesPatternProvider, BackgroundIndexer worker)
        {
            PowershellFileParser parser = null;
            Queue<string> pathsToEnumerate = new Queue<string>();

            if (File.Exists(path) && filesPatternProvider.DoesFileMatch(path))
            {
                parser = new PowershellFileParser(path, isDirectory: false);
                yield return parser;
                ReportProgress(worker, path);
                yield break;
            }
            if (!Directory.Exists(path) || !filesPatternProvider.DoesDirectoryMatch(path))
            {
                yield break;
            }
            parser = new PowershellFileParser(path, isDirectory: true);
            yield return parser;
            pathsToEnumerate.Enqueue(path);
            while (pathsToEnumerate.Any())
            {
                IEnumerable<string> dirs = null;
                parser = null;
                string currentPath = pathsToEnumerate.Dequeue();

                foreach (var file in GetFilesInDirectory(currentPath, filesPatternProvider))
                {
                    yield return file;
                }

                try {
                    dirs = Directory.EnumerateDirectories(currentPath).Where(dir => filesPatternProvider.DoesDirectoryMatch(dir));
                } catch (Exception e)
                {
                    parser = new PowershellFileParser(currentPath, isDirectory: true, errorMessage: e.Message);
                }
                if (parser != null)
                {
                    yield return parser;
                    continue;
                }
                foreach (string dir in dirs)
                {
                    if (filesPatternProvider.DoesDirectoryMatch(dir) && (filesPatternProvider.IncludeAllFiles || filesPatternProvider.IsInAdditonalPaths(dir)))
                    {
                        parser = new PowershellFileParser(dir, isDirectory: true);
                        yield return parser;
                    }
                    pathsToEnumerate.Enqueue(dir);
                }
                ReportProgress(worker, currentPath);
            } while (pathsToEnumerate.Any());
        }