public async Task AddSolutionToWorkspace_ChangeFileInAddedSolution() { FilePath rootProject = Util.GetSampleProject("FileWatcherTest", "Root.csproj"); string workspaceFile = rootProject.ParentDirectory.Combine("Workspace", "FileWatcherTest.mdw"); using (var workspace = (Workspace)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), workspaceFile)) { await FileWatcherService.Add(workspace); string solFile = rootProject.ParentDirectory.Combine("FileWatcherTest", "FileWatcherTest3.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var file = p.Files.First(f => f.FilePath.FileName == "MyClass.cs"); workspace.Items.Add(sol); await workspace.SaveAsync(Util.GetMonitor()); var otherFile = workspace.FileName.ParentDirectory.Combine("test.txt"); ClearFileEventsCaptured(); // Make sure file watcher is updated since adding the new solution // will start a task and may not have finished. So force an update here. await FileWatcherService.Update(); TextFileUtility.WriteText(file.FilePath, string.Empty, Encoding.UTF8); await WaitForFileChanged(file.FilePath); AssertFileChanged(file.FilePath); Assert.IsFalse(file.FilePath.IsChildPathOf(workspace.BaseDirectory)); workspace.Items.Remove(sol); await workspace.SaveAsync(Util.GetMonitor()); await FileWatcherService.Update(); ClearFileEventsCaptured(); TextFileUtility.WriteText(file.FilePath, string.Empty, Encoding.UTF8); TextFileUtility.WriteText(otherFile, string.Empty, Encoding.UTF8); await WaitForFilesChanged(new [] { file.FilePath, otherFile }); Assert.IsFalse(fileChanges.Any(f => f.FileName == file.FilePath)); } }
public async Task DeleteProjectFileExternally() { string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; ClearFileEventsCaptured(); await FileWatcherService.Add(sol); var file = p.Files.First(f => f.FilePath.FileName == "Program.cs"); File.Delete(file.FilePath); await WaitForFileRemoved(file.FilePath); AssertFileRemoved(file.FilePath); }
public async Task AddFile_FileOutsideSolutionDirectory() { FilePath rootProject = Util.GetSampleProject("FileWatcherTest", "Root.csproj"); string solFile = rootProject.ParentDirectory.Combine("FileWatcherTest", "FileWatcherTest3.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var file2 = p.Files.First(f => f.FilePath.FileName == "MyClass.cs"); ClearFileEventsCaptured(); await FileWatcherService.Add(sol); var newFile = rootProject.ParentDirectory.Combine("Library", "MyClass.cs"); var file = new ProjectFile(newFile); file.Link = "LinkedMyClass.cs"; p.AddFile(file); await FileWatcherService.Update(); ClearFileEventsCaptured(); TextFileUtility.WriteText(file.FilePath, string.Empty, Encoding.UTF8); await WaitForFileChanged(file.FilePath); AssertFileChanged(file.FilePath); Assert.IsFalse(file.FilePath.IsChildPathOf(p.BaseDirectory)); Assert.IsFalse(file.FilePath.IsChildPathOf(sol.BaseDirectory)); // After removing the file no events should be generated for the file. p.Files.Remove(file); await FileWatcherService.Update(); ClearFileEventsCaptured(); TextFileUtility.WriteText(file.FilePath, string.Empty, Encoding.UTF8); TextFileUtility.WriteText(file2.FilePath, string.Empty, Encoding.UTF8); await WaitForFilesChanged(new [] { file.FilePath, file2.FilePath }); AssertFileChanged(file2.FilePath); Assert.IsFalse(fileChanges.Any(f => f.FileName == file.FilePath)); }
public async Task ExternalRenameTemporaryFileToFileInProject() { string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var file = p.Files.First(f => f.FilePath.FileName == "Program.cs"); var tempFile = file.FilePath.ChangeExtension(".cs-temp"); File.WriteAllText(tempFile, "test"); ClearFileEventsCaptured(); await FileWatcherService.Add(sol); FileService.SystemRename(tempFile, file.FilePath); await WaitForFileChanged(file.FilePath); AssertFileChanged(file.FilePath); }
public async Task SaveProjectFileExternally_FileOutsideSolutionDirectory() { FilePath rootProject = Util.GetSampleProject("FileWatcherTest", "Root.csproj"); string solFile = rootProject.ParentDirectory.Combine("FileWatcherTest", "FileWatcherTest2.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var file = p.Files.First(f => f.FilePath.FileName == "MyClass.cs"); ClearFileEventsCaptured(); await FileWatcherService.Add(sol); TextFileUtility.WriteText(file.FilePath, string.Empty, Encoding.UTF8); await WaitForFileChanged(file.FilePath); AssertFileChanged(file.FilePath); Assert.IsFalse(file.FilePath.IsChildPathOf(p.BaseDirectory)); Assert.IsFalse(file.FilePath.IsChildPathOf(sol.BaseDirectory)); }
public async Task SaveProject_AfterModifying() { string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; p.DefaultNamespace = "Test"; ClearFileEventsCaptured(); ResetFileServiceChangedEventHandler(); await FileWatcherService.Add(sol); await p.SaveAsync(Util.GetMonitor()); await WaitForFileChanged(p.FileName); AssertFileChanged(p.FileName); Assert.IsFalse(p.NeedsReload); }
public async Task AddNewProjectToSolution_ChangeFileInNewProject() { FilePath rootProject = Util.GetSampleProject("FileWatcherTest", "Root.csproj"); string solFile = rootProject.ParentDirectory.Combine("FileWatcherTest", "FileWatcherTest3.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var otherFile = p.Files.First(f => f.FilePath.FileName == "MyClass.cs"); await FileWatcherService.Add(sol); var libraryProjectFile = rootProject.ParentDirectory.Combine("Library", "Library.csproj"); var p2 = (DotNetProject)await sol.RootFolder.AddItem(Util.GetMonitor(), libraryProjectFile); await sol.SaveAsync(Util.GetMonitor()); var file = p2.Files.First(f => f.FilePath.FileName == "MyClass.cs"); await FileWatcherService.Update(); ClearFileEventsCaptured(); TextFileUtility.WriteText(file.FilePath, string.Empty, Encoding.UTF8); await WaitForFileChanged(file.FilePath); AssertFileChanged(file.FilePath); Assert.IsFalse(file.FilePath.IsChildPathOf(sol.BaseDirectory)); sol.RootFolder.Items.Remove(p2); p2.Dispose(); await sol.SaveAsync(Util.GetMonitor()); await FileWatcherService.Update(); ClearFileEventsCaptured(); TextFileUtility.WriteText(file.FilePath, string.Empty, Encoding.UTF8); TextFileUtility.WriteText(otherFile.FilePath, string.Empty, Encoding.UTF8); await WaitForFilesChanged(new [] { file.FilePath, otherFile.FilePath }); Assert.IsFalse(fileChanges.Any(f => f.FileName == file.FilePath)); }
public async Task SaveFileInProjectExternallyAfterSolutionNotWatched_NoFileChangeEventsFired() { string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var file = p.Files.First(f => f.FilePath.FileName == "Program.cs"); ClearFileEventsCaptured(); await FileWatcherService.Add(sol); sol.Dispose(); sol = null; TextFileUtility.WriteText(file.FilePath, string.Empty, Encoding.UTF8); await WaitForFileChanged(file.FilePath); Assert.AreEqual(0, fileChanges.Count); }
public async Task WatchDirectories_TwoFilesChanged_OneClosed() { FilePath rootSolFile = Util.GetSampleProject("FileWatcherTest", "Root.sln"); var file1 = rootSolFile.ParentDirectory.Combine("FileWatcherTest", "MyClass.cs"); var file2 = rootSolFile.ParentDirectory.Combine("Library", "Properties", "AssemblyInfo.cs"); var id = new object(); try { var directories = new [] { file1.ParentDirectory, file2.ParentDirectory }; await FileWatcherService.WatchDirectories(id, directories); TextFileUtility.WriteText(file1, string.Empty, Encoding.UTF8); TextFileUtility.WriteText(file2, string.Empty, Encoding.UTF8); await WaitForFilesChanged(new [] { file1, file2 }); AssertFileChanged(file1); AssertFileChanged(file2); // Unwatch one directory. directories = new [] { file1.ParentDirectory }; await FileWatcherService.WatchDirectories(id, directories); ClearFileEventsCaptured(); fileChangesTask = new TaskCompletionSource <bool> (); TextFileUtility.WriteText(file2, string.Empty, Encoding.UTF8); TextFileUtility.WriteText(file1, string.Empty, Encoding.UTF8); await WaitForFilesChanged(new [] { file1, file2 }); AssertFileChanged(file1); Assert.IsFalse(fileChanges.Any(f => f.FileName == file2)); } finally { await FileWatcherService.WatchDirectories(id, null); } }
public async Task SaveProjectFileExternally_ProjectOutsideSolutionDirectory() { FilePath rootProject = Util.GetSampleProject("FileWatcherTest", "Root.csproj"); string solFile = rootProject.ParentDirectory.Combine("FileWatcherTest", "FileWatcherTest.sln"); using var sol = (Solution) await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p1 = (DotNetProject)sol.Items [0]; var p2 = (DotNetProject)sol.Items [1]; var file1 = p1.Files.First(f => f.FilePath.FileName == "MyClass.cs"); var file2 = p2.Files.First(f => f.FilePath.FileName == "MyClass.cs"); await FileWatcherService.Add(sol); ClearFileEventsCaptured(); TextFileUtility.WriteText(file1.FilePath, string.Empty, Encoding.UTF8); TextFileUtility.WriteText(file2.FilePath, string.Empty, Encoding.UTF8); await WaitForFilesChanged(new [] { file1.FilePath, file2.FilePath }); AssertFileChanged(file1.FilePath); AssertFileChanged(file2.FilePath); }
public async Task FileChangeCalledWhenPerformGeneratorAsyncInvoked() { string projectFile = Util.GetSampleProject("project-with-corecompiledepends", "project.csproj"); var project = (Project)await Services.ProjectService.ReadSolutionItem(Util.GetMonitor(), projectFile); // FIXME: we need to mimic the project load step because MonoDevelopWorkspace calls this on project load // this has the effect of initialising the cache for GetSourceFilesAsync, which makes change detection work once the project has loaded // for when PerformGeneratorAsync is called. this also causes the file to be written on load if it is not present, which doesn't // help us simulate the target changing the file await project.GetSourceFilesAsync(project.Configurations[0].Selector); // clean it out so that the call to `PerformGeneratorAsync` can create it instead, that's what we want to test var generatedFileName = Path.Combine(project.ItemDirectory, "GeneratedFile.g.cs"); if (File.Exists(generatedFileName)) { File.Delete(generatedFileName); } var id = new object(); try { waitingForFileNameChange = generatedFileName; await FileWatcherService.WatchDirectories(id, new [] { project.BaseDirectory }); await project.PerformGeneratorAsync(project.Configurations[0].Selector, "UpdateGeneratedFiles"); // we need to wait for the file notification to be posted await Task.Run(() => { fileChangeNotification.Task.Wait(TimeSpan.FromMilliseconds(10000)); }); Assert.IsTrue(fileChangeNotification.Task.IsCompleted, "Performing the generator should have fired a file change event"); project.Dispose(); } finally { await FileWatcherService.WatchDirectories(id, null); } }
public async Task TemporaryFileOutsideMonitoredDirectoriesRenamedToFileInProject2() { string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var file = p.Files.First(f => f.FilePath.FileName == "Program.cs"); var newFile = file.FilePath.ChangeName("Test"); ClearFileEventsCaptured(); await FileWatcherService.Add(sol); // Create a new file in the project directory. Ideally Program.cs would be created here but that // seems to generate Changed, Created and Deleted events on the Mac if the file already exists. using (var stream = File.Create(newFile)) { stream.Close(); } await WaitForFileChanged(newFile); AssertFileChanged(newFile); }
public void NormalizeDirectories2() { FilePath fileName = Util.GetSampleProject("FileWatcherTest", "Root.sln"); FilePath rootDirectory = fileName.ParentDirectory; var bDirectory = rootDirectory.Combine("..", "b").FullPath; var dDirectory = rootDirectory.Combine("..", "d").FullPath; var directories = new [] { rootDirectory.Combine("a"), bDirectory, rootDirectory, rootDirectory.Combine("c"), dDirectory }; var normalized = FileWatcherService.Normalize(directories).ToArray(); Assert.AreEqual(3, normalized.Length); Assert.That(normalized, Contains.Item(rootDirectory)); Assert.That(normalized, Contains.Item(bDirectory)); Assert.That(normalized, Contains.Item(dDirectory)); }
public async Task TemporaryFileOutsideMonitoredDirectoriesRenamedToFileInProject() { // Create temp file outside monitored directories. FilePath tempDirectory = Util.CreateTmpDir("temp-rename"); var tempFile = tempDirectory.Combine("Program.cs-temp"); File.WriteAllText(tempFile, "test"); string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var file = p.Files.First(f => f.FilePath.FileName == "Program.cs"); ClearFileEventsCaptured(); await FileWatcherService.Add(sol); // Move temp file to Program.cs that is being monitored for changes. FileService.SystemRename(tempFile, file.FilePath); await WaitForFileChanged(file.FilePath); AssertFileChanged(file.FilePath); }
public async Task GetRootDirectories_WindowsPathUsedForProjectItem_EmptyDirectoryNotIncluded() { if (Platform.IsWindows) { Assert.Ignore("Not valid on Windows"); } FilePath solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln"); using var sol = (Solution) await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile); var p = (DotNetProject)sol.Items [0]; var fileName = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\MSBuild\MSBuild.dll"; var reference = ProjectReference.CreateAssemblyFileReference(fileName); p.References.Add(reference); var directories = FileWatcherService.GetPathsToWatch(sol); Assert.IsFalse(directories.Contains(FilePath.Empty)); Assert.IsFalse(directories.Contains(FilePath.Null)); Assert.AreEqual(1, directories.Count); Assert.IsTrue(directories.First() == sol.BaseDirectory); }
public async Task Reloading() { using (Solution sol = TestProjectsChecks.CreateConsoleSolution("reloading")) { await sol.SaveAsync(Util.GetMonitor()); Assert.IsFalse(sol.NeedsReload); await FileWatcherService.Add(sol); Project p = sol.Items [0] as Project; Assert.IsFalse(p.NeedsReload); // Changing format must reset the reload flag (it's like we just created a new solution in memory) sol.ConvertToFormat(MSBuildFileFormat.VS2010); Assert.IsFalse(sol.NeedsReload); Assert.IsFalse(p.NeedsReload); sol.ConvertToFormat(MSBuildFileFormat.VS2012); Assert.IsFalse(sol.NeedsReload); Assert.IsFalse(p.NeedsReload); sol.RootFolder.Items.Remove(p); Assert.IsFalse(p.NeedsReload); p.FileFormat = MSBuildFileFormat.VS2012; Assert.IsFalse(p.NeedsReload); sol.RootFolder.Items.Add(p); Assert.IsFalse(p.NeedsReload); sol.RootFolder.Items.Remove(p); Assert.IsFalse(p.NeedsReload); p.FileFormat = MSBuildFileFormat.VS2005; Assert.IsFalse(p.NeedsReload); sol.RootFolder.Items.Add(p); Assert.IsFalse(p.NeedsReload); string solFile2 = Util.GetSampleProject("csharp-console", "csharp-console.sln"); using (Solution sol2 = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile2)) { Project p2 = sol2.Items [0] as Project; Assert.IsFalse(sol2.NeedsReload); Assert.IsFalse(p2.NeedsReload); await FileWatcherService.Add(sol2); // Check reloading flag in another solution string solFile = sol.FileName; using (Solution sol3 = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) { Assert.IsFalse(sol3.NeedsReload); await FileWatcherService.Add(sol3); Project p3 = sol3.Items [0] as Project; Assert.IsFalse(p3.NeedsReload); System.Threading.Thread.Sleep(1000); try { fileChangeNotification = new TaskCompletionSource <bool> (); waitForFileChange = sol.FileName; FileService.FileChanged += OnFileChanged; sol.Description = "Foo"; // Small change to force the solution file save await sol.SaveAsync(Util.GetMonitor()); // we need to wait for the file notification to be posted await Task.Run(() => { fileChangeNotification.Task.Wait(TimeSpan.FromMilliseconds(10000)); }); Assert.IsTrue(fileChangeNotification.Task.IsCompleted); } finally { FileService.FileChanged -= OnFileChanged; } Assert.IsTrue(sol3.NeedsReload); } } } }