/// <summary> /// <see cref="_expandedGraphContexts"/> remembers graph expanded or checked so far. /// Each context represents one level in the graph, i.e. a node and its first level dependencies /// Tracking changes over all expanded contexts ensures that all levels are processed /// and updated when there are any changes in nodes data. /// </summary> private void TrackChanges(SnapshotChangedEventArgs updatedProjectContext) { IList <IGraphContext> expandedContexts; lock (_expandedGraphContexts) { expandedContexts = _expandedGraphContexts.ToList(); } if (expandedContexts.Count == 0) { return; } var actionHandlers = _graphActionHandlers.Select(x => x.Value).Where(x => x.CanHandleChanges()).ToList(); if (actionHandlers.Count == 0) { return; } foreach (IGraphContext graphContext in expandedContexts) { try { foreach (IDependenciesGraphActionHandler actionHandler in actionHandlers) { actionHandler.HandleChanges(graphContext, updatedProjectContext); } } finally { // Calling OnCompleted ensures that the changes are reflected in UI graphContext.OnCompleted(); } } }
public Task <IReadOnlyCollection <IPageMetadata> > GetPagesAsync() { return(Task.FromResult((IReadOnlyCollection <IPageMetadata>)PropertyPages.Select(p => p.Value).ToList().AsReadOnly())); }
private void UpdateDependenciesSnapshotAsync( ImmutableDictionary <ITargetFramework, IDependenciesChanges> changes, IProjectCatalogSnapshot catalogs, ITargetFramework activeTargetFramework, CancellationToken token) { IImmutableSet <string> projectItemSpecs = GetProjectItemSpecsFromSnapshot(); bool anyChanges = false; // Note: we are updating existing snapshot, not receiving a complete new one. Thus we must // ensure incremental updates are done in the correct order. This lock ensures that here. lock (_snapshotLock) { var updatedSnapshot = DependenciesSnapshot.FromChanges( _commonServices.Project.FullPath, _currentSnapshot, changes, catalogs, activeTargetFramework, _snapshotFilters.Select(x => x.Value).ToList(), _subTreeProviders.ToDictionary(p => p.Value.ProviderType, p => p.Value), projectItemSpecs); if (!ReferenceEquals(_currentSnapshot, updatedSnapshot)) { _currentSnapshot = updatedSnapshot; anyChanges = true; } } if (anyChanges) { // avoid unnecessary tree updates ScheduleDependenciesUpdate(token); } return; IImmutableSet <string> GetProjectItemSpecsFromSnapshot() { // We don't have catalog snapshot, we're likely updating because one of our project // dependencies changed. Just return 'no data' if (catalogs == null) { return(null); } ImmutableHashSet <string> .Builder itemSpecs = ImmutableHashSet.CreateBuilder(StringComparer.OrdinalIgnoreCase); foreach (ProjectItemInstance item in catalogs.Project.ProjectInstance.Items) { if (item.IsImported()) { continue; } // Returns unescaped evaluated include string itemSpec = item.EvaluatedInclude; if (itemSpec.Length != 0) { itemSpecs.Add(itemSpec); } } return(itemSpecs.ToImmutable()); } }