protected void OnDependenciesChanged(IDependenciesChangeDiff changes, IProjectVersionedValue < Tuple <IProjectSubscriptionUpdate, IProjectCatalogSnapshot, IProjectSharedFoldersSnapshot> > e, RuleHandlerType handlerType) { IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions = null; lock (_syncObject) { if (_latestDataSourceVersions == null) { // very first time send some versions even for Evaluation dataSourceVersions = e?.DataSourceVersions; } _latestDataSourceVersions = e?.DataSourceVersions; if (handlerType == RuleHandlerType.DesignTimeBuild) { // Only update versions after DesignTimeBuild events, since they would bring resolved // dependencies and if some components would want to known when tree latest state changed, // DesignTimeBuild events are the ones that bring final state. dataSourceVersions = _latestDataSourceVersions; } } DependenciesChanged(this, new DependenciesChangedEventArgs( this, changes, e?.Value?.Item2, dataSourceVersions)); }
/// <summary> /// Discovers if there any changes to apply for existing node, after it's context changed. /// </summary> private bool AnyChangesToTrack(IDependencyNode node, IDependencyNode updatedNode, IDependenciesChangeDiff diff, out IEnumerable <IDependencyNode> nodesToAdd, out IEnumerable <IDependencyNode> nodesToRemove) { var existingChildren = node.Children; if (node.Flags.Contains(DependencyNode.DependsOnOtherProviders)) { var remove = new HashSet <IDependencyNode>(diff.RemovedNodes); var add = new HashSet <IDependencyNode>(diff.AddedNodes); foreach (var changedNode in diff.UpdatedNodes) { remove.Add(changedNode); add.Add(changedNode); } nodesToAdd = add; nodesToRemove = remove; } else { var updatedChildren = updatedNode.Children; var comparer = new DependencyNodeResolvedStateComparer(); nodesToRemove = existingChildren.Except(updatedChildren, comparer).ToList(); nodesToAdd = updatedChildren.Except(existingChildren, comparer).ToList(); } return(nodesToAdd.Any() || nodesToRemove.Any()); }
public DependenciesChangedEventArgs(IProjectDependenciesSubTreeProvider provider, IDependenciesChangeDiff changes, IProjectCatalogSnapshot catalogs, IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions) { Provider = provider; Changes = changes; Catalogs = catalogs; DataSourceVersions = dataSourceVersions; }
protected void OnDependenciesChanged(IDependenciesChangeDiff changes, IProjectVersionedValue < Tuple <IProjectSubscriptionUpdate, IProjectCatalogSnapshot, IProjectSharedFoldersSnapshot> > e) { DependenciesChanged(this, new DependenciesChangedEventArgs( this, changes, e?.Value?.Item2, e?.DataSourceVersions)); }
/// <summary> /// Creates or updates a project tree for a given IProjectDependenciesSubTreeProvider /// </summary> /// <param name="dependenciesNode"></param> /// <param name="subTreeProvider"></param> /// <param name="changes"></param> /// <param name="catalogs">Can be null if sub tree provider does not use design time build</param> /// <param name="cancellationToken"></param> /// <returns>IProjectTree for root Dependencies node</returns> private IProjectTree CreateOrUpdateSubTreeProviderNode(IProjectTree dependenciesNode, IProjectDependenciesSubTreeProvider subTreeProvider, IDependenciesChangeDiff changes, IProjectCatalogSnapshot catalogs, CancellationToken cancellationToken) { Requires.NotNull(dependenciesNode, nameof(dependenciesNode)); Requires.NotNull(subTreeProvider, nameof(subTreeProvider)); Requires.NotNull(subTreeProvider.RootNode, nameof(subTreeProvider.RootNode)); Requires.NotNullOrEmpty(subTreeProvider.RootNode.Caption, nameof(subTreeProvider.RootNode.Caption)); Requires.NotNullOrEmpty(subTreeProvider.ProviderType, nameof(subTreeProvider.ProviderType)); var projectFolder = Path.GetDirectoryName(UnconfiguredProject.FullPath); var providerRootTreeNode = GetSubTreeRootNode(dependenciesNode, subTreeProvider.RootNode.Flags); if (subTreeProvider.RootNode.HasChildren || subTreeProvider.ShouldBeVisibleWhenEmpty) { bool newNode = false; if (providerRootTreeNode == null) { providerRootTreeNode = NewTree( caption: subTreeProvider.RootNode.Caption, visible: true, filePath: subTreeProvider.RootNode.Id.ToString(), browseObjectProperties: null, flags: subTreeProvider.RootNode.Flags, icon: subTreeProvider.RootNode.Icon.ToProjectSystemType(), expandedIcon: subTreeProvider.RootNode.ExpandedIcon.ToProjectSystemType()); newNode = true; } if (changes != null) { foreach (var removedItem in changes.RemovedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = FindProjectTreeNode(providerRootTreeNode, removedItem, projectFolder); if (treeNode != null) { providerRootTreeNode = treeNode.Remove(); } } foreach (var updatedItem in changes.UpdatedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = FindProjectTreeNode(providerRootTreeNode, updatedItem, projectFolder); if (treeNode != null) { var updatedNodeParentContext = GetCustomPropertyContext(treeNode.Parent); var updatedValues = new ReferencesProjectTreeCustomizablePropertyValues { Caption = updatedItem.Caption, Flags = updatedItem.Flags, Icon = updatedItem.Icon.ToProjectSystemType(), ExpandedIcon = updatedItem.ExpandedIcon.ToProjectSystemType() }; ApplyProjectTreePropertiesCustomization(updatedNodeParentContext, updatedValues); // update existing tree node properties treeNode = treeNode.SetProperties( caption: updatedItem.Caption, flags: updatedItem.Flags, icon: updatedItem.Icon.ToProjectSystemType(), expandedIcon: updatedItem.ExpandedIcon.ToProjectSystemType()); providerRootTreeNode = treeNode.Parent; } } foreach (var addedItem in changes.AddedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = FindProjectTreeNode(providerRootTreeNode, addedItem, projectFolder); if (treeNode == null) { treeNode = CreateProjectItemTreeNode(providerRootTreeNode, addedItem, catalogs); providerRootTreeNode = providerRootTreeNode.Add(treeNode).Parent; } } } if (newNode) { dependenciesNode = dependenciesNode.Add(providerRootTreeNode).Parent; } else { dependenciesNode = providerRootTreeNode.Parent; } } else { if (providerRootTreeNode != null) { dependenciesNode = dependenciesNode.Remove(providerRootTreeNode); } } return(dependenciesNode); }
/// <summary> /// Creates or updates a project tree for a given IProjectDependenciesSubTreeProvider /// </summary> /// <param name="dependenciesNode"></param> /// <param name="subTreeProvider"></param> /// <param name="changes"></param> /// <param name="catalogs">Can be null if sub tree provider does not use design time build</param> /// <param name="cancellationToken"></param> /// <returns>IProjectTree for root Dependencies node</returns> private IProjectTree CreateOrUpdateSubTreeProviderNode(IProjectTree dependenciesNode, IProjectDependenciesSubTreeProvider subTreeProvider, IDependenciesChangeDiff changes, IProjectCatalogSnapshot catalogs, CancellationToken cancellationToken) { Requires.NotNull(dependenciesNode, nameof(dependenciesNode)); Requires.NotNull(subTreeProvider, nameof(subTreeProvider)); Requires.NotNull(subTreeProvider.RootNode, nameof(subTreeProvider.RootNode)); Requires.NotNullOrEmpty(subTreeProvider.RootNode.Caption, nameof(subTreeProvider.RootNode.Caption)); Requires.NotNullOrEmpty(subTreeProvider.ProviderType, nameof(subTreeProvider.ProviderType)); var providerRootTreeNode = GetSubTreeRootNode(dependenciesNode, subTreeProvider.RootNode.Flags); if (subTreeProvider.RootNode.HasChildren || subTreeProvider.ShouldBeVisibleWhenEmpty) { bool newNode = false; if (providerRootTreeNode == null) { providerRootTreeNode = NewTree( caption: subTreeProvider.RootNode.Caption, visible: true, filePath: subTreeProvider.RootNode.Id.ToString(), browseObjectProperties: null, flags: subTreeProvider.RootNode.Flags, icon: subTreeProvider.RootNode.Icon.ToProjectSystemType(), expandedIcon: subTreeProvider.RootNode.ExpandedIcon.ToProjectSystemType()); newNode = true; } if (changes != null) { foreach (var removedItem in changes.RemovedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = providerRootTreeNode.FindNodeByPath(removedItem.Id.ToString()); if (treeNode != null) { providerRootTreeNode = treeNode.Remove(); } } foreach (var updatedItem in changes.UpdatedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = providerRootTreeNode.FindNodeByPath(updatedItem.Id.ToString()); if (treeNode != null) { var updatedNodeParentContext = GetCustomPropertyContext(treeNode.Parent); var updatedValues = new ReferencesProjectTreeCustomizablePropertyValues { Caption = updatedItem.Caption, Flags = updatedItem.Flags, Icon = updatedItem.Icon.ToProjectSystemType(), ExpandedIcon = updatedItem.ExpandedIcon.ToProjectSystemType() }; ApplyProjectTreePropertiesCustomization(updatedNodeParentContext, updatedValues); // update existing tree node properties treeNode = treeNode.SetProperties( caption: updatedItem.Caption, flags: updatedItem.Flags, icon: updatedItem.Icon.ToProjectSystemType(), expandedIcon: updatedItem.ExpandedIcon.ToProjectSystemType()); providerRootTreeNode = treeNode.Parent; } } var configuredProjectExports = GetActiveConfiguredProjectExports(ActiveConfiguredProject); foreach (var addedItem in changes.AddedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = providerRootTreeNode.FindNodeByPath(addedItem.Id.ToString()); if (treeNode == null) { IRule rule = null; if (addedItem.Properties != null) { // when itemSpec is not in valid absolute path format, property page does not show // item name correctly. var itemSpec = addedItem.Flags.Contains(DependencyNode.CustomItemSpec) ? addedItem.Caption : addedItem.Id.ItemSpec; var itemContext = ProjectPropertiesContext.GetContext(UnconfiguredProject, addedItem.Id.ItemType, itemSpec); if (addedItem.Resolved) { rule = GetRuleForResolvableReference( itemContext, new KeyValuePair <string, IImmutableDictionary <string, string> >( addedItem.Id.ItemSpec, addedItem.Properties), catalogs, configuredProjectExports); } else { rule = GetRuleForUnresolvableReference( itemContext, catalogs, configuredProjectExports); } } // Notify about tree changes to customization context var customTreePropertyContext = GetCustomPropertyContext(providerRootTreeNode); var customTreePropertyValues = new ReferencesProjectTreeCustomizablePropertyValues { Caption = addedItem.Caption, Flags = addedItem.Flags, Icon = addedItem.Icon.ToProjectSystemType() }; ApplyProjectTreePropertiesCustomization(customTreePropertyContext, customTreePropertyValues); treeNode = NewTree(caption: addedItem.Caption, visible: true, filePath: addedItem.Id.ToString(), browseObjectProperties: rule, flags: addedItem.Flags, icon: addedItem.Icon.ToProjectSystemType(), expandedIcon: addedItem.ExpandedIcon.ToProjectSystemType()); providerRootTreeNode = providerRootTreeNode.Add(treeNode).Parent; } } } if (newNode) { dependenciesNode = dependenciesNode.Add(providerRootTreeNode).Parent; } else { dependenciesNode = providerRootTreeNode.Parent; } } else { if (providerRootTreeNode != null) { dependenciesNode = dependenciesNode.Remove(providerRootTreeNode); } } return(dependenciesNode); }
public ProjectContextEventArgs(IDependenciesGraphProjectContext context, IDependenciesChangeDiff diff = null) { Context = context; Diff = diff ?? new DependenciesChange().GetDiff(); }