rename and delete fs events for files

This commit is contained in:
Matt Parker
2025-10-22 00:50:02 +10:00
parent a403cb3389
commit 588299ef39
5 changed files with 60 additions and 0 deletions

View File

@@ -803,4 +803,11 @@ public class RoslynAnalysis
var updatedSolution = _workspace.CurrentSolution.WithDocumentFilePath(document, sharpIdeFile.Path);
_workspace.TryApplyChanges(updatedSolution);
}
public async Task RenameDocument(SharpIdeFile sharpIdeFile, string oldFilePath)
{
var documentId = _workspace!.CurrentSolution.GetDocumentIdsWithFilePath(oldFilePath).Single();
var updatedSolution = _workspace.CurrentSolution.WithDocumentName(documentId, sharpIdeFile.Name);
_workspace.TryApplyChanges(updatedSolution);
}
}

View File

@@ -23,6 +23,15 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
public SharpIdeSolutionModel SolutionModel { get; set; } = null!;
public async Task SharpIdeFileRenamed(SharpIdeFile file, string oldFilePath)
{
if (file.IsRoslynWorkspaceFile)
{
await HandleWorkspaceFileRenamed(file, oldFilePath);
}
// TODO: handle csproj moved
}
public async Task SharpIdeFileMoved(SharpIdeFile file, string oldFilePath)
{
if (file.IsRoslynWorkspaceFile)
@@ -145,4 +154,15 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts.Token);
}
private async Task HandleWorkspaceFileRenamed(SharpIdeFile file, string oldFilePath)
{
var newCts = new CancellationTokenSource();
var oldCts = Interlocked.Exchange(ref _updateSolutionDiagnosticsCts, newCts);
await oldCts.CancelAsync();
oldCts.Dispose();
await _roslynAnalysis.MoveDocument(file, oldFilePath);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts.Token);
}
}

View File

@@ -16,11 +16,27 @@ public class IdeFileExternalChangeHandler
_sharpIdeSolutionModificationService = sharpIdeSolutionModificationService;
GlobalEvents.Instance.FileSystemWatcherInternal.FileChanged.Subscribe(OnFileChanged);
GlobalEvents.Instance.FileSystemWatcherInternal.FileCreated.Subscribe(OnFileCreated);
GlobalEvents.Instance.FileSystemWatcherInternal.FileDeleted.Subscribe(OnFileDeleted);
GlobalEvents.Instance.FileSystemWatcherInternal.FileRenamed.Subscribe(OnFileRenamed);
GlobalEvents.Instance.FileSystemWatcherInternal.DirectoryCreated.Subscribe(OnFolderCreated);
GlobalEvents.Instance.FileSystemWatcherInternal.DirectoryDeleted.Subscribe(OnFolderDeleted);
GlobalEvents.Instance.FileSystemWatcherInternal.DirectoryRenamed.Subscribe(OnFolderRenamed);
}
private async Task OnFileRenamed(string oldFilePath, string newFilePath)
{
var sharpIdeFile = SolutionModel.AllFiles.SingleOrDefault(f => f.Path == oldFilePath);
if (sharpIdeFile is null) return;
await _sharpIdeSolutionModificationService.RenameFile(sharpIdeFile, Path.GetFileName(newFilePath));
}
private async Task OnFileDeleted(string filePath)
{
var sharpIdeFile = SolutionModel.AllFiles.SingleOrDefault(f => f.Path == filePath);
if (sharpIdeFile is null) return;
await _sharpIdeSolutionModificationService.RemoveFile(sharpIdeFile);
}
// TODO: Test - this most likely only will ever be called on linux - windows and macos(?) does delete + create on rename of folders
private async Task OnFolderRenamed(string oldFolderPath, string newFolderPath)
{

View File

@@ -151,4 +151,14 @@ public class SharpIdeSolutionModificationService(FileChangedService fileChangedS
await _fileChangedService.SharpIdeFileMoved(fileToMove, oldPath);
return fileToMove;
}
public async Task<SharpIdeFile> RenameFile(SharpIdeFile fileToRename, string renamedFileName)
{
var oldPath = fileToRename.Path;
var newFilePath = Path.Combine(Path.GetDirectoryName(oldPath)!, renamedFileName);
fileToRename.Name = renamedFileName;
fileToRename.Path = newFilePath;
await _fileChangedService.SharpIdeFileRenamed(fileToRename, oldPath);
return fileToRename;
}
}

View File

@@ -282,6 +282,13 @@ public partial class SolutionExplorerPanel : MarginContainer
fileItem.SetText(0, sharpIdeFile.Name);
fileItem.SetIcon(0, CsharpFileIcon);
fileItem.SetMetadata(0, new RefCountedContainer<SharpIdeFile>(sharpIdeFile));
Observable.EveryValueChanged(sharpIdeFile, folder => folder.Name)
.Skip(1).SubscribeAwait(async (s, ct) =>
{
await this.InvokeAsync(() => fileItem.SetText(0, s));
}).AddTo(this);
return fileItem;
}