private void ComputeFileCollection(FileSystemTreeSnapshot snapshot) { Logger.Log("Computing list of searchable files from FileSystemTree."); var ssw = new ScopedStopWatch(); var directories = FileSystemSnapshotVisitor.GetDirectories(snapshot).ToList(); ssw.Step(sw => Logger.Log("Done flattening file system tree snapshot in {0:n0} msec.", sw.ElapsedMilliseconds)); var directoryNames = directories .Select(x => x.Value.DirectoryName) .ToArray(); ssw.Step(sw => Logger.Log("Done creating array of directory names in {0:n0} msec.", sw.ElapsedMilliseconds)); var searchableFiles = directories .AsParallel() .SelectMany(x => x.Value.Files.Select(y => KeyValuePair.Create(x.Key, y))) .Select(x => new FileInfo(new FileData(x.Value, null), x.Key.IsFileSearchable(x.Value))) .ToList(); ssw.Step(sw => Logger.Log("Done creating list of files in {0:n0} msec.", sw.ElapsedMilliseconds)); var files = searchableFiles .ToDictionary(x => x.FileData.FileName, x => x); ssw.Step(sw => Logger.Log("Done creating dictionary of files in {0:n0} msec.", sw.ElapsedMilliseconds)); Logger.Log("Done computing list of searchable files from FileSystemTree."); Logger.LogMemoryStats(); _files = new FileNameDictionary <FileInfo>(files); _directoryNames = directoryNames; }
private DirectorySnapshot ProcessProject(IFileSystemNameFactory fileNameFactory, IProject project, IProgressTracker progress) { var projectPath = fileNameFactory.CreateAbsoluteDirectoryName(project.RootPath); var ssw = new ScopedStopWatch(); // Create list of pairs (DirectoryName, List[FileNames]) var directoriesWithFiles = TraverseFileSystem(fileNameFactory, project, projectPath) .AsParallel() .WithExecutionMode(ParallelExecutionMode.ForceParallelism) .Select(traversedDirectoryEntry => { var directoryName = traversedDirectoryEntry.DirectoryName; if (progress.Step()) { progress.DisplayProgress((i, n) => string.Format("Traversing directory: {0}\\{1}", project.RootPath.FullName, directoryName.RelativePathName.RelativeName)); } var entries = traversedDirectoryEntry.ChildrenNames .Where(childFilename => project.FileFilter.Include(childFilename.RelativePathName.RelativeName)) .OrderBy(x => x.RelativePathName) .ToReadOnlyCollection(); return(KeyValuePair.Create(directoryName, entries)); }) .ToList(); ssw.Step(sw => Logger.Log("Done traversing file system in {0:n0} msec.", sw.ElapsedMilliseconds)); // We sort entries by directory name *descending* to make sure we process // directories bottom up, so that we know // 1) it is safe to skip DirectoryEntry instances where "Entries.Count" == 0, // 2) we create instances of child directories before their parent. directoriesWithFiles.Sort((x, y) => - x.Key.RelativePathName.CompareTo(y.Key.RelativePathName)); ssw.Step(sw => Logger.Log("Done sorting list of directories in {0:n0} msec.", sw.ElapsedMilliseconds)); // Build map from parent directory -> list of child directories var directoriesToChildDirectories = new Dictionary <DirectoryName, List <DirectoryName> >(); directoriesWithFiles.ForAll(x => { var directoryName = x.Key; // Ignore root project directory name if (directoryName.IsAbsoluteName) { return; } GetOrCreateList(directoriesToChildDirectories, directoryName.Parent).Add(directoryName); }); ssw.Step(sw => Logger.Log("Done creating children directories in {0:n0} msec.", sw.ElapsedMilliseconds)); // Build directory snapshots for each directory entry, using an // intermediate map to enable connecting snapshots to their parent. var directoriesToSnapshot = new Dictionary <DirectoryName, DirectorySnapshot>(); var directorySnapshots = directoriesWithFiles.Select(entry => { var directoryName = entry.Key; var childFilenames = entry.Value; var childDirectories = GetOrEmptyList(directoriesToChildDirectories, directoryName) .Select(x => directoriesToSnapshot[x]) .OrderBy(x => x.DirectoryName.RelativePathName) .ToReadOnlyCollection(); // TODO(rpaquay): Not clear the lines below are a perf win, even though // they do not hurt correctness. // Remove children since we processed them //GetOrEmptyList(directoriesToChildDirectories, directoryName) // .ForAll(x => directoriesToSnapshot.Remove(x)); var result = new DirectorySnapshot(directoryName, childDirectories, childFilenames); directoriesToSnapshot.Add(directoryName, result); return(result); }) .ToList(); ssw.Step(sw => Logger.Log("Done creating directory snapshots in {0:n0} msec.", sw.ElapsedMilliseconds)); // Since we sort directories by name descending, the last entry is always the // entry correcsponding to the project root. Debug.Assert(directorySnapshots.Count >= 1); Debug.Assert(directorySnapshots.Last().DirectoryName.Equals(projectPath)); return(directorySnapshots.Last()); }