public VisualStudioFileChangeTrackerFactory( ForegroundDispatcher foregroundDispatcher, ErrorReporter errorReporter, IVsAsyncFileChangeEx fileChangeService, JoinableTaskContext joinableTaskContext) { if (foregroundDispatcher == null) { throw new ArgumentNullException(nameof(foregroundDispatcher)); } if (errorReporter == null) { throw new ArgumentNullException(nameof(errorReporter)); } if (fileChangeService == null) { throw new ArgumentNullException(nameof(fileChangeService)); } if (joinableTaskContext is null) { throw new ArgumentNullException(nameof(joinableTaskContext)); } _foregroundDispatcher = foregroundDispatcher; _errorReporter = errorReporter; _joinableTaskContext = joinableTaskContext; _fileChangeService = fileChangeService; }
public VisualStudioFileChangeTrackerFactory( ErrorReporter errorReporter, IVsAsyncFileChangeEx fileChangeService, ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, JoinableTaskContext joinableTaskContext) { if (errorReporter is null) { throw new ArgumentNullException(nameof(errorReporter)); } if (fileChangeService is null) { throw new ArgumentNullException(nameof(fileChangeService)); } if (projectSnapshotManagerDispatcher is null) { throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); } if (joinableTaskContext is null) { throw new ArgumentNullException(nameof(joinableTaskContext)); } _errorReporter = errorReporter; _fileChangeService = fileChangeService; _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher; _joinableTaskContext = joinableTaskContext; }
public VisualStudioFileChangeTracker( string filePath, ForegroundDispatcher foregroundDispatcher, ErrorReporter errorReporter, IVsAsyncFileChangeEx fileChangeService, JoinableTaskFactory joinableTaskFactory) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(filePath)); } if (foregroundDispatcher == null) { throw new ArgumentNullException(nameof(foregroundDispatcher)); } if (errorReporter == null) { throw new ArgumentNullException(nameof(errorReporter)); } if (fileChangeService == null) { throw new ArgumentNullException(nameof(fileChangeService)); } FilePath = filePath; _foregroundDispatcher = foregroundDispatcher; _errorReporter = errorReporter; _fileChangeService = fileChangeService; _joinableTaskFactory = joinableTaskFactory ?? throw new ArgumentNullException(); }
protected override void Dispose(bool disposing) { if (disposing) { // Completing the output block before the action block means any final messages that are currently being produced // will not be sent out, which is what we want in this case. _broadcastBlock?.Complete(); _dataSourceLink?.Dispose(); if (_actionBlock != null) { _actionBlock.Complete(); _threadingService.ExecuteSynchronously(async() => { // Wait for any processing to finish so we don't fight over the cookies 🍪 await _actionBlock.Completion; IVsAsyncFileChangeEx vsAsyncFileChangeEx = await _fileChangeService.GetValueAsync(); // Unsubscribe from all files foreach (uint cookie in _fileWatcherCookies.Values) { await vsAsyncFileChangeEx.UnadviseFileChangeAsync(cookie); } }); } } base.Dispose(disposing); }
private async Task UnregisterFileWatcherIfAnyAsync() { // Note file change service is free-threaded if (_filechangeCookie != VSConstants.VSCOOKIE_NIL) { IVsAsyncFileChangeEx fileChangeService = await _fileChangeService.GetValueAsync(); // There's nothing for us to do if this fails. So ignore the return value. await fileChangeService.UnadviseFileChangeAsync(_filechangeCookie); _watchedFileResetCancellationToken?.Cancel(); _watchedFileResetCancellationToken?.Dispose(); _taskDelayScheduler?.Dispose(); } }
private async Task ProcessDesignTimeInputs(IProjectVersionedValue <DesignTimeInputs> input) { DesignTimeInputs designTimeInputs = input.Value; IVsAsyncFileChangeEx vsAsyncFileChangeEx = await _fileChangeService.GetValueAsync(); // we don't care about the difference between types of inputs, so we just construct one hashset for fast comparisons later var allFiles = new HashSet <string>(StringComparers.Paths); allFiles.AddRange(designTimeInputs.Inputs); allFiles.AddRange(designTimeInputs.SharedInputs); // Remove any files we're watching that we don't care about any more var removedFiles = new List <string>(); foreach ((string file, uint cookie) in _fileWatcherCookies) { if (!allFiles.Contains(file)) { await vsAsyncFileChangeEx.UnadviseFileChangeAsync(cookie); removedFiles.Add(file); } } foreach (string file in removedFiles) { _fileWatcherCookies.Remove(file); } // Now watch and output files that are new foreach (string file in allFiles) { if (!_fileWatcherCookies.ContainsKey(file)) { // We don't care about delete and add here, as they come through data flow, plus they are really bouncy - every file change is a Time, Del and Add event) uint cookie = await vsAsyncFileChangeEx.AdviseFileChangeAsync(file, _VSFILECHANGEFLAGS.VSFILECHG_Time | _VSFILECHANGEFLAGS.VSFILECHG_Size, sink : this); _fileWatcherCookies.Add(file, cookie); } } }
public VisualStudioFileChangeTrackerFactoryFactory(ForegroundDispatcher foregroundDispatcher, SVsServiceProvider serviceProvider, JoinableTaskContext joinableTaskContext) { if (foregroundDispatcher == null) { throw new ArgumentNullException(nameof(foregroundDispatcher)); } if (serviceProvider == null) { throw new ArgumentNullException(nameof(serviceProvider)); } if (joinableTaskContext is null) { throw new ArgumentNullException(nameof(joinableTaskContext)); } _foregroundDispatcher = foregroundDispatcher; _joinableTaskContext = joinableTaskContext; _fileChangeService = serviceProvider.GetService(typeof(SVsFileChangeEx)) as IVsAsyncFileChangeEx; }
private async Task RegisterFileWatcherAsync(string projectLockJsonFilePath) { // Note file change service is free-threaded if (projectLockJsonFilePath != null) { _previousContentsHash = GetFileHashOrNull(projectLockJsonFilePath); _taskDelayScheduler?.Dispose(); _taskDelayScheduler = new TaskDelayScheduler( s_notifyDelay, _projectServices.ThreadingService, CreateLinkedCancellationToken()); IVsAsyncFileChangeEx fileChangeService = await _fileChangeService.GetValueAsync(); _filechangeCookie = await fileChangeService.AdviseFileChangeAsync( projectLockJsonFilePath, _VSFILECHANGEFLAGS.VSFILECHG_Time | _VSFILECHANGEFLAGS.VSFILECHG_Size | _VSFILECHANGEFLAGS.VSFILECHG_Add | _VSFILECHANGEFLAGS.VSFILECHG_Del, sink : this); } _fileBeingWatched = projectLockJsonFilePath; }
public VisualStudioFileChangeTracker( string filePath, ErrorReporter errorReporter, IVsAsyncFileChangeEx fileChangeService, ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, JoinableTaskContext joinableTaskContext) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(filePath)); } if (errorReporter is null) { throw new ArgumentNullException(nameof(errorReporter)); } if (fileChangeService is null) { throw new ArgumentNullException(nameof(fileChangeService)); } if (projectSnapshotManagerDispatcher is null) { throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); } if (joinableTaskContext is null) { throw new ArgumentNullException(nameof(joinableTaskContext)); } FilePath = filePath; _errorReporter = errorReporter; _fileChangeService = fileChangeService; _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher; _joinableTaskContext = joinableTaskContext; }
private static DesignTimeInputsFileWatcher CreateDesignTimeInputsFileWatcher(IVsAsyncFileChangeEx fileChangeService, out ProjectValueDataSource <DesignTimeInputs> source) { // Create our mock design time inputs data source, but with a source we can actually use var services = IProjectCommonServicesFactory.CreateWithDefaultThreadingPolicy(); source = ProjectValueDataSourceFactory.Create <DesignTimeInputs>(services); var mock = new Mock <IDesignTimeInputsDataSource>(); mock.SetupGet(s => s.SourceBlock) .Returns(source.SourceBlock); var dataSource = mock.Object; var threadingService = IProjectThreadingServiceFactory.Create(); var unconfiguredProject = UnconfiguredProjectFactory.Create(fullPath: @"C:\MyProject\MyProject.csproj"); var unconfiguredProjectServices = IUnconfiguredProjectServicesFactory.Create( projectService: IProjectServiceFactory.Create( services: ProjectServicesFactory.Create( threadingService: threadingService))); // Create our class under test return(new DesignTimeInputsFileWatcher(unconfiguredProject, unconfiguredProjectServices, threadingService, dataSource, IVsServiceFactory.Create <SVsFileChangeEx, IVsAsyncFileChangeEx>(fileChangeService))); }
public VisualStudioFileChangeTrackerFactoryFactory( SVsServiceProvider serviceProvider, ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, JoinableTaskContext joinableTaskContext) { if (serviceProvider is null) { throw new ArgumentNullException(nameof(serviceProvider)); } if (projectSnapshotManagerDispatcher is null) { throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); } if (joinableTaskContext is null) { throw new ArgumentNullException(nameof(joinableTaskContext)); } _fileChangeService = serviceProvider.GetService(typeof(SVsFileChangeEx)) as IVsAsyncFileChangeEx; _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher; _joinableTaskContext = joinableTaskContext; }