示例#1
0
        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));
            }
        }
示例#2
0
        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);
        }
示例#3
0
        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));
        }
示例#4
0
        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);
        }
示例#5
0
        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));
        }
示例#6
0
        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);
        }
示例#7
0
        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));
        }
示例#8
0
        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);
        }
示例#9
0
        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);
            }
        }
示例#10
0
        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);
        }
示例#11
0
        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);
            }
        }
示例#12
0
        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);
        }
示例#13
0
        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));
        }
示例#14
0
        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);
        }
示例#15
0
        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);
        }
示例#16
0
        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);
                    }
                }
            }
        }