From f65ad7f18c59b8f83b15e217cd765609e6ce648c Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Fri, 10 Oct 2025 00:41:37 +1000 Subject: [PATCH] ignore disk events for files we save --- .../Features/FilePersistence/IdeFileManager.cs | 17 +++++++++++++++-- .../FileWatching/IdeFileChangeHandler.cs | 7 ++++--- .../Features/FileWatching/IdeFileWatcher.cs | 4 ++-- .../Features/SolutionDiscovery/SharpIdeFile.cs | 4 +++- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/SharpIDE.Application/Features/FilePersistence/IdeFileManager.cs b/src/SharpIDE.Application/Features/FilePersistence/IdeFileManager.cs index 1e41c55..6c6691f 100644 --- a/src/SharpIDE.Application/Features/FilePersistence/IdeFileManager.cs +++ b/src/SharpIDE.Application/Features/FilePersistence/IdeFileManager.cs @@ -57,7 +57,7 @@ public class IdeFileManager if (file.IsDirty.Value is false) return; var text = await GetFileTextAsync(file); - await File.WriteAllTextAsync(file.Path, text); + await WriteAllText(file, text); file.IsDirty.Value = false; } @@ -70,10 +70,23 @@ public class IdeFileManager } else { - await File.WriteAllTextAsync(file.Path, newText); + await WriteAllText(file, newText); } } + private static async Task WriteAllText(SharpIdeFile file, string text) + { + file.SuppressDiskChangeEvents.Value = true; + await File.WriteAllTextAsync(file.Path, text); + Console.WriteLine($"Saved file {file.Path}"); + _ = Task.Delay(300).ContinueWith(_ => + { + Console.WriteLine($"Re-enabling disk change events for {file.Path}"); + file.SuppressDiskChangeEvents.Value = false; + Console.WriteLine($"Value is now {file.SuppressDiskChangeEvents.Value}"); + }, CancellationToken.None, TaskContinuationOptions.RunContinuationsAsynchronously, TaskScheduler.Default); + } + public async Task SaveAllOpenFilesAsync() { foreach (var file in _openFiles.Keys.ToList()) diff --git a/src/SharpIDE.Application/Features/FileWatching/IdeFileChangeHandler.cs b/src/SharpIDE.Application/Features/FileWatching/IdeFileChangeHandler.cs index c005dc6..22134f5 100644 --- a/src/SharpIDE.Application/Features/FileWatching/IdeFileChangeHandler.cs +++ b/src/SharpIDE.Application/Features/FileWatching/IdeFileChangeHandler.cs @@ -11,11 +11,12 @@ public class IdeFileChangeHandler GlobalEvents.Instance.FileSystemWatcherInternal.FileChanged.Subscribe(OnFileChanged); } - private async Task OnFileChanged(string arg) + private async Task OnFileChanged(string filePath) { - var sharpIdeFile = SolutionModel.AllFiles.SingleOrDefault(f => f.Path == arg); + var sharpIdeFile = SolutionModel.AllFiles.SingleOrDefault(f => f.Path == filePath); if (sharpIdeFile is null) return; - // TODO: Suppress if SharpIDE changed the file + if (sharpIdeFile.SuppressDiskChangeEvents.Value is true) return; + Console.WriteLine($"IdeFileChangeHandler: Changed - {filePath}"); await sharpIdeFile.FileContentsChangedExternallyFromDisk.InvokeParallelAsync(); } } diff --git a/src/SharpIDE.Application/Features/FileWatching/IdeFileWatcher.cs b/src/SharpIDE.Application/Features/FileWatching/IdeFileWatcher.cs index 747fb45..e01045a 100644 --- a/src/SharpIDE.Application/Features/FileWatching/IdeFileWatcher.cs +++ b/src/SharpIDE.Application/Features/FileWatching/IdeFileWatcher.cs @@ -82,8 +82,8 @@ public sealed class IdeFileWatcher : IDisposable // TODO: Make a note to users that they should not use files without extensions private void HandleChanged(string fullPath) { - if (Path.HasExtension(fullPath) is false) return; - Console.WriteLine($"FileSystemWatcher: Changed - {fullPath}"); + if (Path.HasExtension(fullPath) is false) return; // we don't care about directory changes + //Console.WriteLine($"FileSystemWatcher: Changed - {fullPath}"); GlobalEvents.Instance.FileSystemWatcherInternal.FileChanged.InvokeParallelFireAndForget(fullPath); } diff --git a/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFile.cs b/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFile.cs index 215d2c6..a3a4af6 100644 --- a/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFile.cs +++ b/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFile.cs @@ -15,7 +15,8 @@ public class SharpIdeFile : ISharpIdeNode, IChildSharpIdeNode public bool IsCshtmlFile => Path.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase); public bool IsCsharpFile => Path.EndsWith(".cs", StringComparison.OrdinalIgnoreCase); public bool IsRoslynWorkspaceFile => IsCsharpFile || IsRazorFile || IsCshtmlFile; - public required ReactiveProperty IsDirty { get; set; } + public required ReactiveProperty IsDirty { get; init; } + public required ReactiveProperty SuppressDiskChangeEvents { get; init; } public EventWrapper FileContentsChangedExternallyFromDisk { get; } = new(() => Task.CompletedTask); public EventWrapper FileContentsChangedExternally { get; } = new(() => Task.CompletedTask); @@ -26,6 +27,7 @@ public class SharpIdeFile : ISharpIdeNode, IChildSharpIdeNode Name = name; Parent = parent; IsDirty = new ReactiveProperty(false); + SuppressDiskChangeEvents = new ReactiveProperty(false); allFiles.Add(this); } }